diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 87ed99501..2d4d262f8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,27 +12,37 @@ jobs: strategy: matrix: - node-version: [16.x, 18.x, 20.x] - deno-version: [1.19.x] + node-version: [18.x, 20.x] + bun-version: [1.0.23] + deno-version: [1.42.x] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} + cache: 'npm' - name: Use Deno ${{ matrix.deno-version }} - uses: denolib/setup-deno@v2 + uses: denoland/setup-deno@v1 with: deno-version: ${{ matrix.deno-version }} + - name: Use Bun ${{ matrix.bun-version }} + uses: oven-sh/setup-bun@v1 + with: + bun-version: ${{ matrix.bun-version }} + - name: Install dependencies run: npm ci + - name: Install playwright + run: npx playwright install + - name: Run docker compose - run: docker-compose up -d + run: docker compose up -d - name: Run node tests run: npm test @@ -46,5 +56,11 @@ jobs: - name: Run deno tests run: npm run test:deno + - name: Run bun tests + run: npm run test:bun + - name: Run esbuild test run: npm run test:esbuild + + - name: Run cloudflare workers test + run: npm run test:cloudflare-workers diff --git a/.prettierrc.json b/.prettierrc.json index 00fbdb185..e3b414c7e 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,4 +1,5 @@ { "semi": false, - "singleQuote": true -} \ No newline at end of file + "singleQuote": true, + "trailingComma": "all" +} diff --git a/README.md b/README.md index d1a8dc379..9181c4419 100644 --- a/README.md +++ b/README.md @@ -1,600 +1,47 @@ [![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://stand-with-ukraine.pp.ua) [![Discord](https://img.shields.io/discord/890118421587578920?logo=discord&style=flat)](https://discord.gg/xyBJ3GwvAm) -[![Tests](https://github.com/koskimas/kysely/actions/workflows/test.yml/badge.svg)](https://github.com/koskimas/kysely) +[![Tests](https://github.com/kysely-org/kysely/actions/workflows/test.yml/badge.svg)](https://github.com/kysely-org/kysely) [![License](https://img.shields.io/github/license/kysely-org/kysely?style=flat)](https://github.com/kysely-org/kysely/blob/master/LICENSE) [![Issues](https://img.shields.io/github/issues-closed/kysely-org/kysely?logo=github)](https://github.com/kysely-org/kysely/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) [![Pull Requests](https://img.shields.io/github/issues-pr-closed/kysely-org/kysely?label=PRs&logo=github&style=flat)](https://github.com/kysely-org/kysely/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc) -[![Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/kysely-org/kysely?style=flat&logo=snyk)](https://snyk.io/advisor/npm-package/kysely) [![Downloads](https://img.shields.io/npm/dw/kysely?logo=npm)](https://www.npmjs.com/package/kysely) [![Bundle Size](https://img.shields.io/bundlephobia/minzip/kysely?label=size&logo=npm)](https://bundlephobia.com/package/kysely) [![Social](https://img.shields.io/twitter/follow/kysely_?style=social)](https://twitter.com/kysely_) # [Kysely](https://kysely.dev) -Kysely (pronounce “Key-Seh-Lee”) is a type-safe and autocompletion-friendly typescript SQL query builder. Inspired by -[knex](http://knexjs.org/). Mainly developed for [node.js](https://nodejs.org/en/) but also runs on [deno](https://deno.land/) -and in the browser. +Kysely (pronounce “Key-Seh-Lee”) is a type-safe and autocompletion-friendly [TypeScript](https://www.typescriptlang.org/) [SQL](https://en.wikipedia.org/wiki/SQL) query builder. +Inspired by [Knex.js](http://knexjs.org/). Mainly developed for [Node.js](https://nodejs.org/en/) but also +runs on all other [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript) environments like [Deno](https://deno.com/), [Bun](https://bun.sh/), [Cloudflare Workers](https://workers.cloudflare.com/) +and web browsers. -![](https://github.com/koskimas/kysely/blob/master/assets/demo.gif) +![](https://github.com/kysely-org/kysely/blob/master/assets/demo.gif) Kysely makes sure you only refer to tables and columns that are visible to the part of the query you're writing. The result type only has the selected columns with correct types and aliases. As an added bonus you get autocompletion for all that stuff. -As shown in the gif above, through the pure magic of modern typescript, Kysely is even able to parse +As shown in the gif above, through the pure magic of modern TypeScript, Kysely is even able to parse the alias given to `pet.name` and add the `pet_name` column to the result row type. Kysely is able to infer column names, aliases and types from selected subqueries, joined subqueries, `with` statements and pretty much anything you can think of. Of course there are cases where things cannot be typed at compile time, and Kysely offers escape -hatches for these situations. See the [sql template tag](https://kysely-org.github.io/kysely/interfaces/Sql.html) -and the [DynamicModule](https://kysely-org.github.io/kysely/classes/DynamicModule.html#ref) for more info. +hatches for these situations. See the [sql template tag](https://kysely-org.github.io/kysely-apidoc/interfaces/Sql.html) +and the [DynamicModule](https://kysely-org.github.io/kysely-apidoc/classes/DynamicModule.html#ref) for more info. -All API documentation is written in the typing files and you can simply `cmd-click` on the module, class -or method you're using to see it. The same documentation is also hosted [here](https://github.com/koskimas/kysely). +All API documentation is written in the typing files and you can simply hover over the module, class +or method you're using to see it in your IDE. The same documentation is also hosted [here](https://kysely-org.github.io/kysely-apidoc/). If you start using Kysely and can't find something you'd want to use, please open an issue or join our -[discord server](https://discord.gg/xyBJ3GwvAm). +[Discord server](https://discord.gg/xyBJ3GwvAm). -You can find a more thorough introduction [here](https://www.jakso.me/blog/kysely-a-type-safe-sql-query-builder-for-typescript). +# Getting started -# Table of contents - -- [Installation](#installation) - - [3rd party dialects](#3rd-party-dialects) -- [Minimal example](#minimal-example) -- [Playground](#playground) -- [Generating types](#generating-types) -- [Query examples](#query-examples) - - [Select queries](#select-queries) - - [Stream select query results](#stream-select-query-results) - - [Update queries](#update-queries) - - [Insert queries](#insert-queries) - - [Delete queries](#delete-queries) -- [Recipes](#recipes) -- [Migrations](#migrations) - - [PostgreSQL migration example](#postgresql-migration-example) - - [MySQL migration example](#mysql-migration-example) -- [Deno](#deno) -- [Browser](#browser) -- [Why not just contribute to knex](#why-not-just-contribute-to-knex) - -# Installation - -Kysely currently works on PostgreSQL, MySQL and SQLite. You can install it using: - -``` -# PostgreSQL -npm install kysely pg - -# MySQL -npm install kysely mysql2 - -# SQLite -npm install kysely better-sqlite3 -``` - -More dialects will be added soon. Kysely also has a simple interface -for [3rd party dialects](https://kysely-org.github.io/kysely/interfaces/Dialect.html). - -### 3rd party dialects - - - [PlanetScale Serverless Driver](https://github.com/depot/kysely-planetscale) - - [Cloudflare D1](https://github.com/aidenwallis/kysely-d1) - - [AWS RDS Data API](https://github.com/serverless-stack/kysely-data-api) - - [SurrealDB](https://github.com/igalklebanov/kysely-surrealdb) - - [Neon](https://github.com/seveibar/kysely-neon) - - [AWS S3 Select](https://github.com/igalklebanov/kysely-s3-select) - - [libSQL/sqld](https://github.com/libsql/kysely-libsql) - - [SingleStore Data API](https://github.com/igalklebanov/kysely-singlestore) - - [Postgres.js](https://github.com/igalklebanov/kysely-postgres-js) - - [Fetch driver](https://github.com/andersgee/kysely-fetch-driver) - -# Minimal example - -All you need to do is define an interface for each table in the database and pass those -interfaces to the `Kysely` constructor: - -```ts -import { Pool } from 'pg' -import { - Kysely, - PostgresDialect, - Generated, - ColumnType, - Selectable, - Insertable, - Updateable, -} from 'kysely' - -interface PersonTable { - // Columns that are generated by the database should be marked - // using the `Generated` type. This way they are automatically - // made optional in inserts and updates. - id: Generated - - first_name: string - gender: 'male' | 'female' | 'other' - - // If the column is nullable in the database, make its type nullable. - // Don't use optional properties. Optionality is always determined - // automatically by Kysely. - last_name: string | null - - // You can specify a different type for each operation (select, insert and - // update) using the `ColumnType` - // wrapper. Here we define a column `modified_at` that is selected as - // a `Date`, can optionally be provided as a `string` in inserts and - // can never be updated: - modified_at: ColumnType -} - -interface PetTable { - id: Generated - name: string - owner_id: number - species: 'dog' | 'cat' -} - -interface MovieTable { - id: Generated - stars: number -} - -// Keys of this interface are table names. -interface Database { - person: PersonTable - pet: PetTable - movie: MovieTable -} - -// You'd create one of these when you start your app. -const db = new Kysely({ - // Use MysqlDialect for MySQL and SqliteDialect for SQLite. - dialect: new PostgresDialect({ - pool: new Pool({ - host: 'localhost', - database: 'kysely_test' - }) - }) -}) - -async function demo() { - const { id } = await db - .insertInto('person') - .values({ first_name: 'Jennifer', gender: 'female' }) - .returning('id') - .executeTakeFirstOrThrow() - - await db - .insertInto('pet') - .values({ name: 'Catto', species: 'cat', owner_id: id }) - .execute() - - const person = await db - .selectFrom('person') - .innerJoin('pet', 'pet.owner_id', 'person.id') - .select(['first_name', 'pet.name as pet_name']) - .where('person.id', '=', id) - .executeTakeFirst() - - if (person) { - person.pet_name - } -} -``` - -```ts -// You can extract the select, insert and update interfaces like this -// if you want (you don't need to): -type Person = Selectable -type InsertablePerson = Insertable -type UpdateablePerson = Updateable -``` - -# Playground - -[@wirekang](https://github.com/wirekang) has created a [playground for Kysely](https://kyse.link). You can use to quickly test stuff out and for creating code examples for your issues, PRs and discord messages. - -# Generating types - -To work with Kysely, you're required to provide a database schema type definition to the Kysely constructor. - -In many cases, defining your database schema definitions manually is good enough. - -However, when building production applications, its best to stay aligned with the -database schema, by automatically generating the database schema type definitions. - -There are several ways to do this using 3rd party libraries: - -- [kysely-codegen](https://github.com/RobinBlomberg/kysely-codegen) - This library -generates Kysely database schema type definitions by connecting to and introspecting -your database. This library works with all built-in dialects. - -- [prisma-kysely](https://github.com/valtyr/prisma-kysely) - This library generates -Kysely database schema type definitions from your existing Prisma schemas. - -# Query examples - -## Select queries - -You can find examples of select queries in the documentation of the -[select method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select) and -the [where method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#where) -among other places. - -### Stream select query results - -*Currently only supported by `postgres` and `mysql` dialects.* - -```ts -import { Pool } from 'pg' -// or `import * as Cursor from 'pg-cursor'` depending on your tsconfig -import Cursor from 'pg-cursor' -import { Kysely, PostgresDialect } from 'kysely' - -const db = new Kysely({ - // PostgresDialect requires the Cursor dependency - dialect: new PostgresDialect({ - pool: new Pool({ - host: 'localhost', - database: 'kysely_test' - }), - cursor: Cursor - }), - // MysqlDialect doesn't require any special configuration -}) - -async function demo() { - for await (const adult of db.selectFrom('person') - .selectAll() - .where('age', '>', 18) - .stream() - ) { - console.log(`Hello ${adult.first_name}!`) - - if (adult.first_name === 'John') { - // After this line the db connection is released and no more - // rows are streamed from the database to the client - break; - } - } -} -``` - -## Update queries - -See the [set method](https://kysely-org.github.io/kysely/classes/UpdateQueryBuilder.html#set) and the -[updateTable method](https://kysely-org.github.io/kysely/classes/Kysely.html#updateTable) -documentation. - -## Insert queries - -See the [values method](https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#values) and the -[insertInto method](https://kysely-org.github.io/kysely/classes/Kysely.html#insertInto) -documentation. - -## Delete queries - -See the [deleteFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#deleteFrom) -documentation. - -# Recipes - -The [recipes](https://github.com/koskimas/kysely/tree/master/site/docs/recipes/) folder contains a bunch of small tutorials -or "recipes" for common use cases. - -* [Expressions](https://github.com/koskimas/kysely/tree/master/site/docs/recipes/expressions.md) -* [Conditional selects](https://github.com/koskimas/kysely/tree/master/site/docs/recipes/conditional-selects.md) -* [Dealing with the `Type instantiation is excessively deep and possibly infinite` error](https://github.com/koskimas/kysely/tree/master/site/docs/recipes/excessively-deep-types.md) -* [Deduplicate joins](https://github.com/koskimas/kysely/tree/master/site/docs/recipes/deduplicate-joins.md) -* [Extending kysely](https://github.com/koskimas/kysely/tree/master/site/docs/recipes/extending-kysely.md) -* [Introspecting relation metadata](https://github.com/koskimas/kysely/tree/master/site/docs/recipes/introspecting-relation-metadata.md) -* [Raw SQL](https://github.com/koskimas/kysely/tree/master/site/docs/recipes/raw-sql.md) -* [Relations](https://github.com/koskimas/kysely/tree/master/site/docs/recipes/relations.md) -* [Schemas](https://github.com/koskimas/kysely/tree/master/site/docs/recipes/schemas.md) -* [Splitting build, compile and execute code](https://github.com/koskimas/kysely/tree/master/site/docs/recipes/splitting-build-compile-and-execute-code.md) - -# Migrations - -Migration files should look like this: - -```ts -import { Kysely } from 'kysely' - -export async function up(db: Kysely): Promise { - // Migration code -} - -export async function down(db: Kysely): Promise { - // Migration code -} -``` - -The `up` function is called when you update your database schema to the next version and `down` -when you go back to previous version. The only argument for the functions is an instance of -`Kysely`. It's important to use `Kysely` and not `Kysely`. - -Migrations should never depend on the current code of your app because they need to work even when the app -changes. Migrations need to be "frozen in time". - -The migrations can use the [Kysely.schema](https://kysely-org.github.io/kysely/classes/SchemaModule.html) -module to modify the schema. Migrations can also run normal queries to modify data. - -Execution order of the migrations is the alpabetical order of their names. An excellent way to name your -migrations is to prefix them with an ISO 8601 date string. A date prefix works well in large teams -where multiple team members may add migrations at the same time in parallel commits without knowing -about the other migrations. - -You don't need to store your migrations as separate files if you don't want to. You can easily -implement your own [MigrationProvider](https://kysely-org.github.io/kysely/interfaces/MigrationProvider.html) -and give it to the [Migrator](https://kysely-org.github.io/kysely/classes/Migrator.html) class -when you instantiate one. - -### PostgreSQL migration example - -```ts -import { Kysely, sql } from 'kysely' - -export async function up(db: Kysely): Promise { - await db.schema - .createTable('person') - .addColumn('id', 'serial', (col) => col.primaryKey()) - .addColumn('first_name', 'varchar', (col) => col.notNull()) - .addColumn('last_name', 'varchar') - .addColumn('gender', 'varchar(50)', (col) => col.notNull()) - .addColumn('created_at', 'timestamp', (col) => col.defaultTo(sql`now()`).notNull()) - .execute() - - await db.schema - .createTable('pet') - .addColumn('id', 'serial', (col) => col.primaryKey()) - .addColumn('name', 'varchar', (col) => col.notNull().unique()) - .addColumn('owner_id', 'integer', (col) => - col.references('person.id').onDelete('cascade').notNull() - ) - .addColumn('species', 'varchar', (col) => col.notNull()) - .execute() - - await db.schema - .createIndex('pet_owner_id_index') - .on('pet') - .column('owner_id') - .execute() -} - -export async function down(db: Kysely): Promise { - await db.schema.dropTable('pet').execute() - await db.schema.dropTable('person').execute() -} -``` - -### MySQL migration example - -```ts -import { Kysely } from 'kysely' - -export async function up(db: Kysely): Promise { - await db.schema - .createTable('person') - .addColumn('id', 'integer', (col) => col.autoIncrement().primaryKey()) - .addColumn('first_name', 'varchar(255)', (col) => col.notNull()) - .addColumn('last_name', 'varchar(255)') - .addColumn('gender', 'varchar(50)', (col) => col.notNull()) - .execute() - - await db.schema - .createTable('pet') - .addColumn('id', 'integer', (col) => col.autoIncrement().primaryKey()) - .addColumn('name', 'varchar(255)', (col) => col.notNull().unique()) - .addColumn('owner_id', 'integer', (col) => col.notNull()) - .addColumn('species', 'varchar(255)', (col) => col.notNull()) - .addForeignKeyConstraint( - 'pet_owner_id_fk', ['owner_id'], 'person', ['id'], - (cb) => cb.onDelete('cascade') - ) - .execute() - - await db.schema - .createIndex('pet_owner_id_index') - .on('pet') - .column('owner_id') - .execute() -} - -export async function down(db: Kysely): Promise { - await db.schema.dropTable('pet').execute() - await db.schema.dropTable('person').execute() -} -``` - -You can then use - -```ts -const migrator = new Migrator(migratorConfig); -await migrator.migrateToLatest(pathToMigrationsFolder) -``` - -to run all migrations that have not yet been run. See the -[Migrator](https://kysely-org.github.io/kysely/classes/Migrator.html) -class's documentation for more info. - -Kysely doesn't have a CLI for running migrations and probably never will. This is because Kysely's -migrations are also written in typescript. To run the migrations, you need to first build the -typescript code into javascript. A CLI would cause confusion over which migrations are being -run, the typescript ones or the javascript ones. If we added support for both, the CLI would -need to depend on a typescript compiler, which most production environments don't (and shouldn't) -have. You will probably want to add a simple migration script to your projects like this: - -```ts -import * as path from 'path' -import { Pool } from 'pg' -import { promises as fs } from 'fs' -import { - Kysely, - Migrator, - PostgresDialect, - FileMigrationProvider -} from 'kysely' - -async function migrateToLatest() { - const db = new Kysely({ - dialect: new PostgresDialect({ - pool: new Pool({ - host: 'localhost', - database: 'kysely_test', - }) - }), - }) - - const migrator = new Migrator({ - db, - provider: new FileMigrationProvider({ - fs, - path, - migrationFolder: 'some/path/to/migrations', - }) - }) - - const { error, results } = await migrator.migrateToLatest() - - results?.forEach((it) => { - if (it.status === 'Success') { - console.log(`migration "${it.migrationName}" was executed successfully`) - } else if (it.status === 'Error') { - console.error(`failed to execute migration "${it.migrationName}"`) - } - }) - - if (error) { - console.error('failed to migrate') - console.error(error) - process.exit(1) - } - - await db.destroy() -} - -migrateToLatest() -``` - -The migration methods use a lock on the database level and parallel calls are executed serially. -This means that you can safely call `migrateToLatest` and other migration methods from multiple -server instances simultaneously and the migrations are guaranteed to only be executed once. The -locks are also automatically released if the migration process crashes or the connection to the -database fails. - -# Deno - -Kysely doesn't include drivers for deno, but you can still use Kysely as a query builder -or implement your own driver: - -```ts -// We use jsdeliver to get Kysely from npm. -import { - DummyDriver, - Generated, - Kysely, - PostgresAdapter, - PostgresIntrospector, - PostgresQueryCompiler, -} from 'https://cdn.jsdelivr.net/npm/kysely/dist/esm/index.js' - -interface Person { - id: Generated - first_name: string - last_name: string | null -} - -interface Database { - person: Person -} - -const db = new Kysely({ - dialect: { - createAdapter() { - return new PostgresAdapter() - }, - createDriver() { - // You need a driver to be able to execute queries. In this example - // we use the dummy driver that never does anything. - return new DummyDriver() - }, - createIntrospector(db: Kysely) { - return new PostgresIntrospector(db) - }, - createQueryCompiler() { - return new PostgresQueryCompiler() - }, - }, -}) - -const query = db.selectFrom('person').select('id') -const sql = query.compile() - -console.log(sql.sql) -``` - -# Browser - -Kysely also runs in the browser: - -```ts -import { - Kysely, - Generated, - DummyDriver, - SqliteAdapter, - SqliteIntrospector, - SqliteQueryCompiler, -} from 'kysely' - -interface Person { - id: Generated - first_name: string - last_name: string | null -} - -interface Database { - person: Person -} - -const db = new Kysely({ - dialect: { - createAdapter() { - return new SqliteAdapter() - }, - createDriver() { - return new DummyDriver() - }, - createIntrospector(db: Kysely) { - return new SqliteIntrospector(db) - }, - createQueryCompiler() { - return new SqliteQueryCompiler() - }, - }, -}) - -window.addEventListener('load', () => { - const sql = db.selectFrom('person').select('id').compile() - - const result = document.createElement('span') - result.id = 'result' - result.innerHTML = sql.sql - - document.body.appendChild(result) -}) -``` - -# Why not just contribute to knex - -Kysely is very similar to knex, but it also attempts to fix things that I personally find not-so-good -in knex. Bringing the type system and the changes to knex would mean very significant breaking changes -that aren't possible at this point of the project. Knex was also originally written for javascript and -the typescript typings were added afterwards. That always leads to compromises in the types. Designing -a library for typescript from the ground up produces much better and simpler types. +Please visit our documentation site [kysely.dev](https://kysely.dev) to get started. We also have a comprehensive +API documentation hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same +documentation in your IDE by hovering over a class/method/property/whatever. # Contributors diff --git a/docker-compose.yml b/docker-compose.yml index 6b24bd0f8..f390151c7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,29 @@ version: '3' services: + # credit to Knex.js team for the following mssql setup here: + mssql: + image: mcr.microsoft.com/mssql/server:2022-latest + ports: + - '21433:1433' + environment: + ACCEPT_EULA: Y + MSSQL_PID: Express + SA_PASSWORD: KyselyTest0 + healthcheck: + test: /opt/mssql-tools/bin/sqlcmd -S mssql -U sa -P 'KyselyTest0' -Q 'select 1' + waitmssql: + image: mcr.microsoft.com/mssql/server:2017-latest + links: + - mssql + depends_on: + - mssql + environment: + MSSQL_PID: Express + entrypoint: + - bash + - -c + # https://docs.microsoft.com/en-us/sql/relational-databases/logs/control-transaction-durability?view=sql-server-ver15#bkmk_DbControl + - 'until /opt/mssql-tools/bin/sqlcmd -S mssql -U sa -P KyselyTest0 -d master -Q "CREATE DATABASE kysely_test; ALTER DATABASE kysely_test SET ALLOW_SNAPSHOT_ISOLATION ON; ALTER DATABASE kysely_test SET DELAYED_DURABILITY = FORCED"; do sleep 5; done' mysql: image: 'mysql/mysql-server' environment: @@ -17,4 +41,4 @@ services: POSTGRES_USER: kysely POSTGRES_HOST_AUTH_METHOD: trust ports: - - '5434:5432' \ No newline at end of file + - '5434:5432' diff --git a/docs-theme.css b/docs-theme.css deleted file mode 100644 index 50ec9b1a9..000000000 --- a/docs-theme.css +++ /dev/null @@ -1,15 +0,0 @@ -/* Hide the type parameter listings for methods and such. */ -.tsd-type-parameters-title, -.tsd-type-parameters { - display: none; -} - -/* Add margin around example code blocks */ -.tsd-comment-tags pre { - margin-top: 10px; - margin-bottom: 10px; -} - -.tsd-panel-group.tsd-index-group { - display: none; -} \ No newline at end of file diff --git a/docs/.nojekyll b/docs/.nojekyll deleted file mode 100644 index e2ac6616a..000000000 --- a/docs/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/assets/custom.css b/docs/assets/custom.css deleted file mode 100644 index 50ec9b1a9..000000000 --- a/docs/assets/custom.css +++ /dev/null @@ -1,15 +0,0 @@ -/* Hide the type parameter listings for methods and such. */ -.tsd-type-parameters-title, -.tsd-type-parameters { - display: none; -} - -/* Add margin around example code blocks */ -.tsd-comment-tags pre { - margin-top: 10px; - margin-bottom: 10px; -} - -.tsd-panel-group.tsd-index-group { - display: none; -} \ No newline at end of file diff --git a/docs/assets/demo.gif b/docs/assets/demo.gif deleted file mode 100644 index fc9673743..000000000 Binary files a/docs/assets/demo.gif and /dev/null differ diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css deleted file mode 100644 index dd0721d0e..000000000 --- a/docs/assets/highlight.css +++ /dev/null @@ -1,113 +0,0 @@ -:root { - --light-hl-0: #000000; - --dark-hl-0: #D4D4D4; - --light-hl-1: #001080; - --dark-hl-1: #9CDCFE; - --light-hl-2: #AF00DB; - --dark-hl-2: #C586C0; - --light-hl-3: #A31515; - --dark-hl-3: #CE9178; - --light-hl-4: #0000FF; - --dark-hl-4: #569CD6; - --light-hl-5: #267F99; - --dark-hl-5: #4EC9B0; - --light-hl-6: #008000; - --dark-hl-6: #6A9955; - --light-hl-7: #0070C1; - --dark-hl-7: #4FC1FF; - --light-hl-8: #795E26; - --dark-hl-8: #DCDCAA; - --light-hl-9: #098658; - --dark-hl-9: #B5CEA8; - --light-hl-10: #000000FF; - --dark-hl-10: #D4D4D4; - --light-hl-11: #CD3131; - --dark-hl-11: #F44747; - --light-hl-12: #000000; - --dark-hl-12: #C8C8C8; - --light-code-background: #FFFFFF; - --dark-code-background: #1E1E1E; -} - -@media (prefers-color-scheme: light) { :root { - --hl-0: var(--light-hl-0); - --hl-1: var(--light-hl-1); - --hl-2: var(--light-hl-2); - --hl-3: var(--light-hl-3); - --hl-4: var(--light-hl-4); - --hl-5: var(--light-hl-5); - --hl-6: var(--light-hl-6); - --hl-7: var(--light-hl-7); - --hl-8: var(--light-hl-8); - --hl-9: var(--light-hl-9); - --hl-10: var(--light-hl-10); - --hl-11: var(--light-hl-11); - --hl-12: var(--light-hl-12); - --code-background: var(--light-code-background); -} } - -@media (prefers-color-scheme: dark) { :root { - --hl-0: var(--dark-hl-0); - --hl-1: var(--dark-hl-1); - --hl-2: var(--dark-hl-2); - --hl-3: var(--dark-hl-3); - --hl-4: var(--dark-hl-4); - --hl-5: var(--dark-hl-5); - --hl-6: var(--dark-hl-6); - --hl-7: var(--dark-hl-7); - --hl-8: var(--dark-hl-8); - --hl-9: var(--dark-hl-9); - --hl-10: var(--dark-hl-10); - --hl-11: var(--dark-hl-11); - --hl-12: var(--dark-hl-12); - --code-background: var(--dark-code-background); -} } - -:root[data-theme='light'] { - --hl-0: var(--light-hl-0); - --hl-1: var(--light-hl-1); - --hl-2: var(--light-hl-2); - --hl-3: var(--light-hl-3); - --hl-4: var(--light-hl-4); - --hl-5: var(--light-hl-5); - --hl-6: var(--light-hl-6); - --hl-7: var(--light-hl-7); - --hl-8: var(--light-hl-8); - --hl-9: var(--light-hl-9); - --hl-10: var(--light-hl-10); - --hl-11: var(--light-hl-11); - --hl-12: var(--light-hl-12); - --code-background: var(--light-code-background); -} - -:root[data-theme='dark'] { - --hl-0: var(--dark-hl-0); - --hl-1: var(--dark-hl-1); - --hl-2: var(--dark-hl-2); - --hl-3: var(--dark-hl-3); - --hl-4: var(--dark-hl-4); - --hl-5: var(--dark-hl-5); - --hl-6: var(--dark-hl-6); - --hl-7: var(--dark-hl-7); - --hl-8: var(--dark-hl-8); - --hl-9: var(--dark-hl-9); - --hl-10: var(--dark-hl-10); - --hl-11: var(--dark-hl-11); - --hl-12: var(--dark-hl-12); - --code-background: var(--dark-code-background); -} - -.hl-0 { color: var(--hl-0); } -.hl-1 { color: var(--hl-1); } -.hl-2 { color: var(--hl-2); } -.hl-3 { color: var(--hl-3); } -.hl-4 { color: var(--hl-4); } -.hl-5 { color: var(--hl-5); } -.hl-6 { color: var(--hl-6); } -.hl-7 { color: var(--hl-7); } -.hl-8 { color: var(--hl-8); } -.hl-9 { color: var(--hl-9); } -.hl-10 { color: var(--hl-10); } -.hl-11 { color: var(--hl-11); } -.hl-12 { color: var(--hl-12); } -pre, code { background: var(--code-background); } diff --git a/docs/assets/main.js b/docs/assets/main.js deleted file mode 100644 index f7c83669c..000000000 --- a/docs/assets/main.js +++ /dev/null @@ -1,58 +0,0 @@ -"use strict"; -"use strict";(()=>{var Qe=Object.create;var ae=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var Ce=Object.getOwnPropertyNames;var Oe=Object.getPrototypeOf,Re=Object.prototype.hasOwnProperty;var _e=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var Me=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ce(e))!Re.call(t,i)&&i!==n&&ae(t,i,{get:()=>e[i],enumerable:!(r=Pe(e,i))||r.enumerable});return t};var De=(t,e,n)=>(n=t!=null?Qe(Oe(t)):{},Me(e||!t||!t.__esModule?ae(n,"default",{value:t,enumerable:!0}):n,t));var de=_e((ce,he)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(n){e.console&&console.warn&&console.warn(n)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var h=t.utils.clone(n)||{};h.position=[a,l],h.index=s.length,s.push(new t.Token(r.slice(a,o),h))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. -`,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ou?h+=2:a==u&&(n+=r[l+1]*i[h+1],l+=2,h+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}if(s.str.length==0&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}s.str.length==1&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var h=s.str.charAt(0),m=s.str.charAt(1),v;m in s.node.edges?v=s.node.edges[m]:(v=new t.TokenSet,s.node.edges[m]=v),s.str.length==1&&(v.final=!0),i.push({node:v,editsRemaining:s.editsRemaining-1,str:h+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;u1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,n){typeof define=="function"&&define.amd?define(n):typeof ce=="object"?he.exports=n():e.lunr=n()}(this,function(){return t})})()});var le=[];function B(t,e){le.push({selector:e,constructor:t})}var Y=class{constructor(){this.alwaysVisibleMember=null;this.createComponents(document.body),this.ensureFocusedElementVisible(),window.addEventListener("hashchange",()=>this.ensureFocusedElementVisible())}createComponents(e){le.forEach(n=>{e.querySelectorAll(n.selector).forEach(r=>{r.dataset.hasInstance||(new n.constructor({el:r,app:this}),r.dataset.hasInstance=String(!0))})})}filterChanged(){this.ensureFocusedElementVisible()}ensureFocusedElementVisible(){this.alwaysVisibleMember&&(this.alwaysVisibleMember.classList.remove("always-visible"),this.alwaysVisibleMember.firstElementChild.remove(),this.alwaysVisibleMember=null);let e=document.getElementById(location.hash.substring(1));if(!e)return;let n=e.parentElement;for(;n&&n.tagName!=="SECTION";)n=n.parentElement;if(n&&n.offsetParent==null){this.alwaysVisibleMember=n,n.classList.add("always-visible");let r=document.createElement("p");r.classList.add("warning"),r.textContent="This member is normally hidden due to your filter settings.",n.prepend(r)}}};var I=class{constructor(e){this.el=e.el,this.app=e.app}};var J=class{constructor(){this.listeners={}}addEventListener(e,n){e in this.listeners||(this.listeners[e]=[]),this.listeners[e].push(n)}removeEventListener(e,n){if(!(e in this.listeners))return;let r=this.listeners[e];for(let i=0,s=r.length;i{let n=Date.now();return(...r)=>{n+e-Date.now()<0&&(t(...r),n=Date.now())}};var re=class extends J{constructor(){super();this.scrollTop=0;this.lastY=0;this.width=0;this.height=0;this.showToolbar=!0;this.toolbar=document.querySelector(".tsd-page-toolbar"),this.navigation=document.querySelector(".col-menu"),window.addEventListener("scroll",ne(()=>this.onScroll(),10)),window.addEventListener("resize",ne(()=>this.onResize(),10)),this.searchInput=document.querySelector("#tsd-search input"),this.searchInput&&this.searchInput.addEventListener("focus",()=>{this.hideShowToolbar()}),this.onResize(),this.onScroll()}triggerResize(){let n=new CustomEvent("resize",{detail:{width:this.width,height:this.height}});this.dispatchEvent(n)}onResize(){this.width=window.innerWidth||0,this.height=window.innerHeight||0;let n=new CustomEvent("resize",{detail:{width:this.width,height:this.height}});this.dispatchEvent(n)}onScroll(){this.scrollTop=window.scrollY||0;let n=new CustomEvent("scroll",{detail:{scrollTop:this.scrollTop}});this.dispatchEvent(n),this.hideShowToolbar()}hideShowToolbar(){let n=this.showToolbar;this.showToolbar=this.lastY>=this.scrollTop||this.scrollTop<=0||!!this.searchInput&&this.searchInput===document.activeElement,n!==this.showToolbar&&(this.toolbar.classList.toggle("tsd-page-toolbar--hide"),this.navigation?.classList.toggle("col-menu--hide")),this.lastY=this.scrollTop}},R=re;R.instance=new re;var X=class extends I{constructor(n){super(n);this.anchors=[];this.index=-1;R.instance.addEventListener("resize",()=>this.onResize()),R.instance.addEventListener("scroll",r=>this.onScroll(r)),this.createAnchors()}createAnchors(){let n=window.location.href;n.indexOf("#")!=-1&&(n=n.substring(0,n.indexOf("#"))),this.el.querySelectorAll("a").forEach(r=>{let i=r.href;if(i.indexOf("#")==-1||i.substring(0,n.length)!=n)return;let s=i.substring(i.indexOf("#")+1),o=document.querySelector("a.tsd-anchor[name="+s+"]"),a=r.parentNode;!o||!a||this.anchors.push({link:a,anchor:o,position:0})}),this.onResize()}onResize(){let n;for(let i=0,s=this.anchors.length;ii.position-s.position);let r=new CustomEvent("scroll",{detail:{scrollTop:R.instance.scrollTop}});this.onScroll(r)}onScroll(n){let r=n.detail.scrollTop+5,i=this.anchors,s=i.length-1,o=this.index;for(;o>-1&&i[o].position>r;)o-=1;for(;o-1&&this.anchors[this.index].link.classList.remove("focus"),this.index=o,this.index>-1&&this.anchors[this.index].link.classList.add("focus"))}};var ue=(t,e=100)=>{let n;return()=>{clearTimeout(n),n=setTimeout(()=>t(),e)}};var me=De(de());function ve(){let t=document.getElementById("tsd-search");if(!t)return;let e=document.getElementById("search-script");t.classList.add("loading"),e&&(e.addEventListener("error",()=>{t.classList.remove("loading"),t.classList.add("failure")}),e.addEventListener("load",()=>{t.classList.remove("loading"),t.classList.add("ready")}),window.searchData&&t.classList.remove("loading"));let n=document.querySelector("#tsd-search input"),r=document.querySelector("#tsd-search .results");if(!n||!r)throw new Error("The input field or the result list wrapper was not found");let i=!1;r.addEventListener("mousedown",()=>i=!0),r.addEventListener("mouseup",()=>{i=!1,t.classList.remove("has-focus")}),n.addEventListener("focus",()=>t.classList.add("has-focus")),n.addEventListener("blur",()=>{i||(i=!1,t.classList.remove("has-focus"))});let s={base:t.dataset.base+"/"};Fe(t,r,n,s)}function Fe(t,e,n,r){n.addEventListener("input",ue(()=>{He(t,e,n,r)},200));let i=!1;n.addEventListener("keydown",s=>{i=!0,s.key=="Enter"?Ve(e,n):s.key=="Escape"?n.blur():s.key=="ArrowUp"?pe(e,-1):s.key==="ArrowDown"?pe(e,1):i=!1}),n.addEventListener("keypress",s=>{i&&s.preventDefault()}),document.body.addEventListener("keydown",s=>{s.altKey||s.ctrlKey||s.metaKey||!n.matches(":focus")&&s.key==="/"&&(n.focus(),s.preventDefault())})}function Ae(t,e){t.index||window.searchData&&(e.classList.remove("loading"),e.classList.add("ready"),t.data=window.searchData,t.index=me.Index.load(window.searchData.index))}function He(t,e,n,r){if(Ae(r,t),!r.index||!r.data)return;e.textContent="";let i=n.value.trim(),s=i?r.index.search(`*${i}*`):[];for(let o=0;oa.score-o.score);for(let o=0,a=Math.min(10,s.length);o${fe(u.parent,i)}.${l}`);let h=document.createElement("li");h.classList.value=u.classes??"";let m=document.createElement("a");m.href=r.base+u.url,m.innerHTML=l,h.append(m),e.appendChild(h)}}function pe(t,e){let n=t.querySelector(".current");if(!n)n=t.querySelector(e==1?"li:first-child":"li:last-child"),n&&n.classList.add("current");else{let r=n;if(e===1)do r=r.nextElementSibling??void 0;while(r instanceof HTMLElement&&r.offsetParent==null);else do r=r.previousElementSibling??void 0;while(r instanceof HTMLElement&&r.offsetParent==null);r&&(n.classList.remove("current"),r.classList.add("current"))}}function Ve(t,e){let n=t.querySelector(".current");if(n||(n=t.querySelector("li:first-child")),n){let r=n.querySelector("a");r&&(window.location.href=r.href),e.blur()}}function fe(t,e){if(e==="")return t;let n=t.toLocaleLowerCase(),r=e.toLocaleLowerCase(),i=[],s=0,o=n.indexOf(r);for(;o!=-1;)i.push(ie(t.substring(s,o)),`${ie(t.substring(o,o+r.length))}`),s=o+r.length,o=n.indexOf(r,s);return i.push(ie(t.substring(s))),i.join("")}var Ne={"&":"&","<":"<",">":">","'":"'",'"':"""};function ie(t){return t.replace(/[&<>"'"]/g,e=>Ne[e])}var F="mousedown",ye="mousemove",j="mouseup",Z={x:0,y:0},ge=!1,se=!1,Be=!1,A=!1,xe=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(xe?"is-mobile":"not-mobile");xe&&"ontouchstart"in document.documentElement&&(Be=!0,F="touchstart",ye="touchmove",j="touchend");document.addEventListener(F,t=>{se=!0,A=!1;let e=F=="touchstart"?t.targetTouches[0]:t;Z.y=e.pageY||0,Z.x=e.pageX||0});document.addEventListener(ye,t=>{if(se&&!A){let e=F=="touchstart"?t.targetTouches[0]:t,n=Z.x-(e.pageX||0),r=Z.y-(e.pageY||0);A=Math.sqrt(n*n+r*r)>10}});document.addEventListener(j,()=>{se=!1});document.addEventListener("click",t=>{ge&&(t.preventDefault(),t.stopImmediatePropagation(),ge=!1)});var K=class extends I{constructor(n){super(n);this.className=this.el.dataset.toggle||"",this.el.addEventListener(j,r=>this.onPointerUp(r)),this.el.addEventListener("click",r=>r.preventDefault()),document.addEventListener(F,r=>this.onDocumentPointerDown(r)),document.addEventListener(j,r=>this.onDocumentPointerUp(r))}setActive(n){if(this.active==n)return;this.active=n,document.documentElement.classList.toggle("has-"+this.className,n),this.el.classList.toggle("active",n);let r=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(r),setTimeout(()=>document.documentElement.classList.remove(r),500)}onPointerUp(n){A||(this.setActive(!0),n.preventDefault())}onDocumentPointerDown(n){if(this.active){if(n.target.closest(".col-menu, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(n){if(!A&&this.active&&n.target.closest(".col-menu")){let r=n.target.closest("a");if(r){let i=window.location.href;i.indexOf("#")!=-1&&(i=i.substring(0,i.indexOf("#"))),r.href.substring(0,i.length)==i&&setTimeout(()=>this.setActive(!1),250)}}}};var oe;try{oe=localStorage}catch{oe={getItem(){return null},setItem(){}}}var Q=oe;var Le=document.head.appendChild(document.createElement("style"));Le.dataset.for="filters";var ee=class extends I{constructor(n){super(n);this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),Le.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; } -`}fromLocalStorage(){let n=Q.getItem(this.key);return n?n==="true":this.el.checked}setLocalStorage(n){Q.setItem(this.key,n.toString()),this.value=n,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),this.app.filterChanged(),document.querySelectorAll(".tsd-index-section").forEach(n=>{n.style.display="block";let r=Array.from(n.querySelectorAll(".tsd-index-link")).every(i=>i.offsetParent==null);n.style.display=r?"none":"block"})}};var te=class extends I{constructor(n){super(n);this.calculateHeights(),this.summary=this.el.querySelector(".tsd-accordion-summary"),this.icon=this.summary.querySelector("svg"),this.key=`tsd-accordion-${this.summary.textContent.replace(/\s+/g,"-").toLowerCase()}`,this.setLocalStorage(this.fromLocalStorage(),!0),this.summary.addEventListener("click",r=>this.toggleVisibility(r)),this.icon.style.transform=this.getIconRotation()}getIconRotation(n=this.el.open){return`rotate(${n?0:-90}deg)`}calculateHeights(){let n=this.el.open,{position:r,left:i}=this.el.style;this.el.style.position="fixed",this.el.style.left="-9999px",this.el.open=!0,this.expandedHeight=this.el.offsetHeight+"px",this.el.open=!1,this.collapsedHeight=this.el.offsetHeight+"px",this.el.open=n,this.el.style.height=n?this.expandedHeight:this.collapsedHeight,this.el.style.position=r,this.el.style.left=i}toggleVisibility(n){n.preventDefault(),this.el.style.overflow="hidden",this.el.open?this.collapse():this.expand()}expand(n=!0){this.el.open=!0,this.animate(this.collapsedHeight,this.expandedHeight,{opening:!0,duration:n?300:0})}collapse(n=!0){this.animate(this.expandedHeight,this.collapsedHeight,{opening:!1,duration:n?300:0})}animate(n,r,{opening:i,duration:s=300}){if(this.animation)return;let o={duration:s,easing:"ease"};this.animation=this.el.animate({height:[n,r]},o),this.icon.animate({transform:[this.icon.style.transform||this.getIconRotation(!i),this.getIconRotation(i)]},o).addEventListener("finish",()=>{this.icon.style.transform=this.getIconRotation(i)}),this.animation.addEventListener("finish",()=>this.animationEnd(i))}animationEnd(n){this.el.open=n,this.animation=void 0,this.el.style.height="auto",this.el.style.overflow="visible",this.setLocalStorage(n)}fromLocalStorage(){let n=Q.getItem(this.key);return n?n==="true":this.el.open}setLocalStorage(n,r=!1){this.fromLocalStorage()===n&&!r||(Q.setItem(this.key,n.toString()),this.el.open=n,this.handleValueChange(r))}handleValueChange(n=!1){this.fromLocalStorage()===this.el.open&&!n||(this.fromLocalStorage()?this.expand(!1):this.collapse(!1))}};function be(t){let e=Q.getItem("tsd-theme")||"os";t.value=e,Ee(e),t.addEventListener("change",()=>{Q.setItem("tsd-theme",t.value),Ee(t.value)})}function Ee(t){document.documentElement.dataset.theme=t}ve();B(X,".menu-highlight");B(K,"a[data-toggle]");B(te,".tsd-index-accordion");B(ee,".tsd-filter-item input[type=checkbox]");var we=document.getElementById("theme");we&&be(we);var je=new Y;Object.defineProperty(window,"app",{value:je});})(); -/*! Bundled license information: - -lunr/lunr.js: - (** - * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 - * Copyright (C) 2020 Oliver Nightingale - * @license MIT - *) - (*! - * lunr.utils - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Set - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.tokenizer - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Pipeline - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Vector - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.stemmer - * Copyright (C) 2020 Oliver Nightingale - * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt - *) - (*! - * lunr.stopWordFilter - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.trimmer - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.TokenSet - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Index - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Builder - * Copyright (C) 2020 Oliver Nightingale - *) -*/ diff --git a/docs/assets/search.js b/docs/assets/search.js deleted file mode 100644 index 26177a727..000000000 --- a/docs/assets/search.js +++ /dev/null @@ -1 +0,0 @@ -window.searchData = JSON.parse("{\"kinds\":{\"32\":\"Variable\",\"64\":\"Function\",\"128\":\"Class\",\"256\":\"Interface\",\"512\":\"Constructor\",\"1024\":\"Property\",\"2048\":\"Method\",\"65536\":\"Type literal\",\"262144\":\"Accessor\",\"4194304\":\"Type alias\"},\"rows\":[{\"kind\":256,\"name\":\"ExpressionBuilder\",\"url\":\"interfaces/ExpressionBuilder.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":262144,\"name\":\"fn\",\"url\":\"interfaces/ExpressionBuilder.html#fn\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":2048,\"name\":\"selectFrom\",\"url\":\"interfaces/ExpressionBuilder.html#selectFrom\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":2048,\"name\":\"case\",\"url\":\"interfaces/ExpressionBuilder.html#case\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":2048,\"name\":\"ref\",\"url\":\"interfaces/ExpressionBuilder.html#ref\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":2048,\"name\":\"val\",\"url\":\"interfaces/ExpressionBuilder.html#val\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":2048,\"name\":\"cmpr\",\"url\":\"interfaces/ExpressionBuilder.html#cmpr\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":2048,\"name\":\"bxp\",\"url\":\"interfaces/ExpressionBuilder.html#bxp\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":2048,\"name\":\"unary\",\"url\":\"interfaces/ExpressionBuilder.html#unary\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":2048,\"name\":\"not\",\"url\":\"interfaces/ExpressionBuilder.html#not\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":2048,\"name\":\"exists\",\"url\":\"interfaces/ExpressionBuilder.html#exists\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":2048,\"name\":\"neg\",\"url\":\"interfaces/ExpressionBuilder.html#neg\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":2048,\"name\":\"and\",\"url\":\"interfaces/ExpressionBuilder.html#and\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":2048,\"name\":\"or\",\"url\":\"interfaces/ExpressionBuilder.html#or\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":2048,\"name\":\"withSchema\",\"url\":\"interfaces/ExpressionBuilder.html#withSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ExpressionBuilder\"},{\"kind\":64,\"name\":\"expressionBuilder\",\"url\":\"functions/expressionBuilder-1.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":4194304,\"name\":\"AnyAliasedColumn\",\"url\":\"types/AnyAliasedColumn.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"AnyAliasedColumnWithTable\",\"url\":\"types/AnyAliasedColumnWithTable.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"AnyColumn\",\"url\":\"types/AnyColumn.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"AnyColumnWithTable\",\"url\":\"types/AnyColumnWithTable.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"AnySelectQueryBuilder\",\"url\":\"types/AnySelectQueryBuilder.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"Equals\",\"url\":\"types/Equals.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"UnknownRow\",\"url\":\"types/UnknownRow.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"Simplify\",\"url\":\"types/Simplify.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"SqlBool\",\"url\":\"types/SqlBool.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":64,\"name\":\"logOnce\",\"url\":\"functions/logOnce.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":4194304,\"name\":\"SelectExpression\",\"url\":\"types/SelectExpression.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"SelectArg\",\"url\":\"types/SelectArg.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"Selection\",\"url\":\"types/Selection.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"ReferenceExpression\",\"url\":\"types/ReferenceExpression.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"ReferenceExpressionOrList\",\"url\":\"types/ReferenceExpressionOrList.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"SimpleReferenceExpression\",\"url\":\"types/SimpleReferenceExpression.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"StringReference\",\"url\":\"types/StringReference.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"ExtractTypeFromStringReference\",\"url\":\"types/ExtractTypeFromStringReference.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"ExtractTypeFromReferenceExpression\",\"url\":\"types/ExtractTypeFromReferenceExpression.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"ValueExpression\",\"url\":\"types/ValueExpression.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"ValueExpressionOrList\",\"url\":\"types/ValueExpressionOrList.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"TableExpression\",\"url\":\"types/TableExpression.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"TableExpressionOrList\",\"url\":\"types/TableExpressionOrList.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"JoinReferenceExpression\",\"url\":\"types/JoinReferenceExpression.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"JoinCallbackExpression\",\"url\":\"types/JoinCallbackExpression.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/JoinCallbackExpression.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"JoinCallbackExpression\"},{\"kind\":4194304,\"name\":\"InsertObject\",\"url\":\"types/InsertObject.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"UpdateObject\",\"url\":\"types/UpdateObject.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"OrderByExpression\",\"url\":\"types/OrderByExpression.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"OrderByDirectionExpression\",\"url\":\"types/OrderByDirectionExpression.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"ComparisonOperatorExpression\",\"url\":\"types/ComparisonOperatorExpression.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"OperandValueExpression\",\"url\":\"types/OperandValueExpression.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"OperandValueExpressionOrList\",\"url\":\"types/OperandValueExpressionOrList.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"ExistsExpression\",\"url\":\"types/ExistsExpression.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":64,\"name\":\"isKyselyProps\",\"url\":\"functions/isKyselyProps.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":128,\"name\":\"Kysely\",\"url\":\"classes/Kysely.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/Kysely.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":262144,\"name\":\"schema\",\"url\":\"classes/Kysely.html#schema\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":262144,\"name\":\"dynamic\",\"url\":\"classes/Kysely.html#dynamic\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":262144,\"name\":\"introspection\",\"url\":\"classes/Kysely.html#introspection\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"case\",\"url\":\"classes/Kysely.html#case\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":262144,\"name\":\"fn\",\"url\":\"classes/Kysely.html#fn\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"transaction\",\"url\":\"classes/Kysely.html#transaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"connection\",\"url\":\"classes/Kysely.html#connection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"withPlugin\",\"url\":\"classes/Kysely.html#withPlugin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"withoutPlugins\",\"url\":\"classes/Kysely.html#withoutPlugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"withSchema\",\"url\":\"classes/Kysely.html#withSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"withTables\",\"url\":\"classes/Kysely.html#withTables\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"destroy\",\"url\":\"classes/Kysely.html#destroy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":262144,\"name\":\"isTransaction\",\"url\":\"classes/Kysely.html#isTransaction\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"executeQuery\",\"url\":\"classes/Kysely.html#executeQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"selectFrom\",\"url\":\"classes/Kysely.html#selectFrom\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"insertInto\",\"url\":\"classes/Kysely.html#insertInto\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"replaceInto\",\"url\":\"classes/Kysely.html#replaceInto\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"deleteFrom\",\"url\":\"classes/Kysely.html#deleteFrom\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"updateTable\",\"url\":\"classes/Kysely.html#updateTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"with\",\"url\":\"classes/Kysely.html#with\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Kysely\"},{\"kind\":2048,\"name\":\"withRecursive\",\"url\":\"classes/Kysely.html#withRecursive\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Kysely\"},{\"kind\":128,\"name\":\"Transaction\",\"url\":\"classes/Transaction.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/Transaction.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"Transaction\"},{\"kind\":262144,\"name\":\"isTransaction\",\"url\":\"classes/Transaction.html#isTransaction\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"transaction\",\"url\":\"classes/Transaction.html#transaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"connection\",\"url\":\"classes/Transaction.html#connection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"destroy\",\"url\":\"classes/Transaction.html#destroy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"withPlugin\",\"url\":\"classes/Transaction.html#withPlugin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"withoutPlugins\",\"url\":\"classes/Transaction.html#withoutPlugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"withSchema\",\"url\":\"classes/Transaction.html#withSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"withTables\",\"url\":\"classes/Transaction.html#withTables\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Transaction\"},{\"kind\":262144,\"name\":\"schema\",\"url\":\"classes/Transaction.html#schema\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Transaction\"},{\"kind\":262144,\"name\":\"dynamic\",\"url\":\"classes/Transaction.html#dynamic\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Transaction\"},{\"kind\":262144,\"name\":\"introspection\",\"url\":\"classes/Transaction.html#introspection\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"case\",\"url\":\"classes/Transaction.html#case\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Transaction\"},{\"kind\":262144,\"name\":\"fn\",\"url\":\"classes/Transaction.html#fn\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"executeQuery\",\"url\":\"classes/Transaction.html#executeQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"selectFrom\",\"url\":\"classes/Transaction.html#selectFrom\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"insertInto\",\"url\":\"classes/Transaction.html#insertInto\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"replaceInto\",\"url\":\"classes/Transaction.html#replaceInto\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"deleteFrom\",\"url\":\"classes/Transaction.html#deleteFrom\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"updateTable\",\"url\":\"classes/Transaction.html#updateTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"with\",\"url\":\"classes/Transaction.html#with\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Transaction\"},{\"kind\":2048,\"name\":\"withRecursive\",\"url\":\"classes/Transaction.html#withRecursive\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"Transaction\"},{\"kind\":256,\"name\":\"KyselyProps\",\"url\":\"interfaces/KyselyProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"config\",\"url\":\"interfaces/KyselyProps.html#config\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"KyselyProps\"},{\"kind\":1024,\"name\":\"driver\",\"url\":\"interfaces/KyselyProps.html#driver\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"KyselyProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/KyselyProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"KyselyProps\"},{\"kind\":1024,\"name\":\"dialect\",\"url\":\"interfaces/KyselyProps.html#dialect\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"KyselyProps\"},{\"kind\":256,\"name\":\"KyselyConfig\",\"url\":\"interfaces/KyselyConfig.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"dialect\",\"url\":\"interfaces/KyselyConfig.html#dialect\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"KyselyConfig\"},{\"kind\":1024,\"name\":\"plugins\",\"url\":\"interfaces/KyselyConfig.html#plugins\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"KyselyConfig\"},{\"kind\":1024,\"name\":\"log\",\"url\":\"interfaces/KyselyConfig.html#log\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"KyselyConfig\"},{\"kind\":128,\"name\":\"ConnectionBuilder\",\"url\":\"classes/ConnectionBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/ConnectionBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"ConnectionBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/ConnectionBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ConnectionBuilder\"},{\"kind\":128,\"name\":\"TransactionBuilder\",\"url\":\"classes/TransactionBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/TransactionBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"TransactionBuilder\"},{\"kind\":2048,\"name\":\"setIsolationLevel\",\"url\":\"classes/TransactionBuilder.html#setIsolationLevel\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"TransactionBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/TransactionBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"TransactionBuilder\"},{\"kind\":128,\"name\":\"QueryCreator\",\"url\":\"classes/QueryCreator.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/QueryCreator.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"QueryCreator\"},{\"kind\":2048,\"name\":\"selectFrom\",\"url\":\"classes/QueryCreator.html#selectFrom\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"QueryCreator\"},{\"kind\":2048,\"name\":\"insertInto\",\"url\":\"classes/QueryCreator.html#insertInto\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"QueryCreator\"},{\"kind\":2048,\"name\":\"replaceInto\",\"url\":\"classes/QueryCreator.html#replaceInto\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"QueryCreator\"},{\"kind\":2048,\"name\":\"deleteFrom\",\"url\":\"classes/QueryCreator.html#deleteFrom\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"QueryCreator\"},{\"kind\":2048,\"name\":\"updateTable\",\"url\":\"classes/QueryCreator.html#updateTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"QueryCreator\"},{\"kind\":2048,\"name\":\"with\",\"url\":\"classes/QueryCreator.html#with\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"QueryCreator\"},{\"kind\":2048,\"name\":\"withRecursive\",\"url\":\"classes/QueryCreator.html#withRecursive\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"QueryCreator\"},{\"kind\":2048,\"name\":\"withPlugin\",\"url\":\"classes/QueryCreator.html#withPlugin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"QueryCreator\"},{\"kind\":2048,\"name\":\"withoutPlugins\",\"url\":\"classes/QueryCreator.html#withoutPlugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"QueryCreator\"},{\"kind\":2048,\"name\":\"withSchema\",\"url\":\"classes/QueryCreator.html#withSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"QueryCreator\"},{\"kind\":256,\"name\":\"QueryCreatorProps\",\"url\":\"interfaces/QueryCreatorProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/QueryCreatorProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"QueryCreatorProps\"},{\"kind\":1024,\"name\":\"withNode\",\"url\":\"interfaces/QueryCreatorProps.html#withNode\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"QueryCreatorProps\"},{\"kind\":64,\"name\":\"isExpression\",\"url\":\"functions/isExpression.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":64,\"name\":\"isAliasedExpression\",\"url\":\"functions/isAliasedExpression.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":256,\"name\":\"Expression\",\"url\":\"interfaces/Expression.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":262144,\"name\":\"expressionType\",\"url\":\"interfaces/Expression.html#expressionType\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-interface\",\"parent\":\"Expression\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"interfaces/Expression.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Expression\"},{\"kind\":256,\"name\":\"AliasedExpression\",\"url\":\"interfaces/AliasedExpression.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":262144,\"name\":\"expression\",\"url\":\"interfaces/AliasedExpression.html#expression\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-interface\",\"parent\":\"AliasedExpression\"},{\"kind\":262144,\"name\":\"alias\",\"url\":\"interfaces/AliasedExpression.html#alias\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-interface\",\"parent\":\"AliasedExpression\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"interfaces/AliasedExpression.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"AliasedExpression\"},{\"kind\":128,\"name\":\"ExpressionWrapper\",\"url\":\"classes/ExpressionWrapper.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/ExpressionWrapper.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"ExpressionWrapper\"},{\"kind\":2048,\"name\":\"as\",\"url\":\"classes/ExpressionWrapper.html#as\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ExpressionWrapper\"},{\"kind\":2048,\"name\":\"$castTo\",\"url\":\"classes/ExpressionWrapper.html#_castTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ExpressionWrapper\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/ExpressionWrapper.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ExpressionWrapper\"},{\"kind\":128,\"name\":\"AliasedExpressionWrapper\",\"url\":\"classes/AliasedExpressionWrapper.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/AliasedExpressionWrapper.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"AliasedExpressionWrapper\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/AliasedExpressionWrapper.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AliasedExpressionWrapper\"},{\"kind\":256,\"name\":\"WhereInterface\",\"url\":\"interfaces/WhereInterface.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"where\",\"url\":\"interfaces/WhereInterface.html#where\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhereInterface\"},{\"kind\":2048,\"name\":\"whereRef\",\"url\":\"interfaces/WhereInterface.html#whereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhereInterface\"},{\"kind\":2048,\"name\":\"orWhere\",\"url\":\"interfaces/WhereInterface.html#orWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhereInterface\"},{\"kind\":2048,\"name\":\"orWhereRef\",\"url\":\"interfaces/WhereInterface.html#orWhereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhereInterface\"},{\"kind\":2048,\"name\":\"whereExists\",\"url\":\"interfaces/WhereInterface.html#whereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhereInterface\"},{\"kind\":2048,\"name\":\"whereNotExists\",\"url\":\"interfaces/WhereInterface.html#whereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhereInterface\"},{\"kind\":2048,\"name\":\"orWhereExists\",\"url\":\"interfaces/WhereInterface.html#orWhereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhereInterface\"},{\"kind\":2048,\"name\":\"orWhereNotExists\",\"url\":\"interfaces/WhereInterface.html#orWhereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhereInterface\"},{\"kind\":2048,\"name\":\"clearWhere\",\"url\":\"interfaces/WhereInterface.html#clearWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"WhereInterface\"},{\"kind\":4194304,\"name\":\"WhereExpressionFactory\",\"url\":\"types/WhereExpressionFactory.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/WhereExpressionFactory.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"WhereExpressionFactory\"},{\"kind\":256,\"name\":\"ReturningInterface\",\"url\":\"interfaces/ReturningInterface.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"returning\",\"url\":\"interfaces/ReturningInterface.html#returning\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ReturningInterface\"},{\"kind\":2048,\"name\":\"returningAll\",\"url\":\"interfaces/ReturningInterface.html#returningAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ReturningInterface\"},{\"kind\":256,\"name\":\"HavingInterface\",\"url\":\"interfaces/HavingInterface.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"having\",\"url\":\"interfaces/HavingInterface.html#having\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"HavingInterface\"},{\"kind\":2048,\"name\":\"havingRef\",\"url\":\"interfaces/HavingInterface.html#havingRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"HavingInterface\"},{\"kind\":2048,\"name\":\"orHaving\",\"url\":\"interfaces/HavingInterface.html#orHaving\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"HavingInterface\"},{\"kind\":2048,\"name\":\"orHavingRef\",\"url\":\"interfaces/HavingInterface.html#orHavingRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"HavingInterface\"},{\"kind\":2048,\"name\":\"havingExists\",\"url\":\"interfaces/HavingInterface.html#havingExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"HavingInterface\"},{\"kind\":2048,\"name\":\"havingNotExists\",\"url\":\"interfaces/HavingInterface.html#havingNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"HavingInterface\"},{\"kind\":2048,\"name\":\"orHavingExists\",\"url\":\"interfaces/HavingInterface.html#orHavingExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"HavingInterface\"},{\"kind\":2048,\"name\":\"orHavingNotExists\",\"url\":\"interfaces/HavingInterface.html#orHavingNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"HavingInterface\"},{\"kind\":4194304,\"name\":\"HavingExpressionFactory\",\"url\":\"types/HavingExpressionFactory.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/HavingExpressionFactory.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"HavingExpressionFactory\"},{\"kind\":128,\"name\":\"SelectQueryBuilder\",\"url\":\"classes/SelectQueryBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/SelectQueryBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"where\",\"url\":\"classes/SelectQueryBuilder.html#where\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"whereRef\",\"url\":\"classes/SelectQueryBuilder.html#whereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"orWhere\",\"url\":\"classes/SelectQueryBuilder.html#orWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"orWhereRef\",\"url\":\"classes/SelectQueryBuilder.html#orWhereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"whereExists\",\"url\":\"classes/SelectQueryBuilder.html#whereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"whereNotExists\",\"url\":\"classes/SelectQueryBuilder.html#whereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"orWhereExists\",\"url\":\"classes/SelectQueryBuilder.html#orWhereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"orWhereNotExists\",\"url\":\"classes/SelectQueryBuilder.html#orWhereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"having\",\"url\":\"classes/SelectQueryBuilder.html#having\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"havingRef\",\"url\":\"classes/SelectQueryBuilder.html#havingRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"orHaving\",\"url\":\"classes/SelectQueryBuilder.html#orHaving\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"orHavingRef\",\"url\":\"classes/SelectQueryBuilder.html#orHavingRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"havingExists\",\"url\":\"classes/SelectQueryBuilder.html#havingExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"havingNotExist\",\"url\":\"classes/SelectQueryBuilder.html#havingNotExist\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"havingNotExists\",\"url\":\"classes/SelectQueryBuilder.html#havingNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"orHavingExists\",\"url\":\"classes/SelectQueryBuilder.html#orHavingExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"orHavingNotExists\",\"url\":\"classes/SelectQueryBuilder.html#orHavingNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"select\",\"url\":\"classes/SelectQueryBuilder.html#select\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"distinctOn\",\"url\":\"classes/SelectQueryBuilder.html#distinctOn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"modifyFront\",\"url\":\"classes/SelectQueryBuilder.html#modifyFront\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"modifyEnd\",\"url\":\"classes/SelectQueryBuilder.html#modifyEnd\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"distinct\",\"url\":\"classes/SelectQueryBuilder.html#distinct\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"forUpdate\",\"url\":\"classes/SelectQueryBuilder.html#forUpdate\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"forShare\",\"url\":\"classes/SelectQueryBuilder.html#forShare\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"forKeyShare\",\"url\":\"classes/SelectQueryBuilder.html#forKeyShare\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"forNoKeyUpdate\",\"url\":\"classes/SelectQueryBuilder.html#forNoKeyUpdate\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"skipLocked\",\"url\":\"classes/SelectQueryBuilder.html#skipLocked\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"noWait\",\"url\":\"classes/SelectQueryBuilder.html#noWait\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"selectAll\",\"url\":\"classes/SelectQueryBuilder.html#selectAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"innerJoin\",\"url\":\"classes/SelectQueryBuilder.html#innerJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"leftJoin\",\"url\":\"classes/SelectQueryBuilder.html#leftJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"rightJoin\",\"url\":\"classes/SelectQueryBuilder.html#rightJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"fullJoin\",\"url\":\"classes/SelectQueryBuilder.html#fullJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"innerJoinLateral\",\"url\":\"classes/SelectQueryBuilder.html#innerJoinLateral\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"leftJoinLateral\",\"url\":\"classes/SelectQueryBuilder.html#leftJoinLateral\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"orderBy\",\"url\":\"classes/SelectQueryBuilder.html#orderBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"groupBy\",\"url\":\"classes/SelectQueryBuilder.html#groupBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"limit\",\"url\":\"classes/SelectQueryBuilder.html#limit\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"offset\",\"url\":\"classes/SelectQueryBuilder.html#offset\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"union\",\"url\":\"classes/SelectQueryBuilder.html#union\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"unionAll\",\"url\":\"classes/SelectQueryBuilder.html#unionAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"intersect\",\"url\":\"classes/SelectQueryBuilder.html#intersect\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"intersectAll\",\"url\":\"classes/SelectQueryBuilder.html#intersectAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"except\",\"url\":\"classes/SelectQueryBuilder.html#except\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"exceptAll\",\"url\":\"classes/SelectQueryBuilder.html#exceptAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"as\",\"url\":\"classes/SelectQueryBuilder.html#as\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"clearSelect\",\"url\":\"classes/SelectQueryBuilder.html#clearSelect\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"clearWhere\",\"url\":\"classes/SelectQueryBuilder.html#clearWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"clearLimit\",\"url\":\"classes/SelectQueryBuilder.html#clearLimit\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"clearOffset\",\"url\":\"classes/SelectQueryBuilder.html#clearOffset\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"clearOrderBy\",\"url\":\"classes/SelectQueryBuilder.html#clearOrderBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/SelectQueryBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"call\",\"url\":\"classes/SelectQueryBuilder.html#call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"$if\",\"url\":\"classes/SelectQueryBuilder.html#_if\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"if\",\"url\":\"classes/SelectQueryBuilder.html#if\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"$castTo\",\"url\":\"classes/SelectQueryBuilder.html#_castTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"castTo\",\"url\":\"classes/SelectQueryBuilder.html#castTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"$narrowType\",\"url\":\"classes/SelectQueryBuilder.html#_narrowType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"$assertType\",\"url\":\"classes/SelectQueryBuilder.html#_assertType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"assertType\",\"url\":\"classes/SelectQueryBuilder.html#assertType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"withPlugin\",\"url\":\"classes/SelectQueryBuilder.html#withPlugin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/SelectQueryBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/SelectQueryBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/SelectQueryBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"executeTakeFirst\",\"url\":\"classes/SelectQueryBuilder.html#executeTakeFirst\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"executeTakeFirstOrThrow\",\"url\":\"classes/SelectQueryBuilder.html#executeTakeFirstOrThrow\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"stream\",\"url\":\"classes/SelectQueryBuilder.html#stream\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":2048,\"name\":\"explain\",\"url\":\"classes/SelectQueryBuilder.html#explain\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SelectQueryBuilder\"},{\"kind\":256,\"name\":\"SelectQueryBuilderProps\",\"url\":\"interfaces/SelectQueryBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/SelectQueryBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryBuilderProps\"},{\"kind\":1024,\"name\":\"queryNode\",\"url\":\"interfaces/SelectQueryBuilderProps.html#queryNode\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/SelectQueryBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryBuilderProps\"},{\"kind\":128,\"name\":\"AliasedSelectQueryBuilder\",\"url\":\"classes/AliasedSelectQueryBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/AliasedSelectQueryBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"AliasedSelectQueryBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/AliasedSelectQueryBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AliasedSelectQueryBuilder\"},{\"kind\":4194304,\"name\":\"SelectQueryBuilderWithInnerJoin\",\"url\":\"types/SelectQueryBuilderWithInnerJoin.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"SelectQueryBuilderWithLeftJoin\",\"url\":\"types/SelectQueryBuilderWithLeftJoin.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"SelectQueryBuilderWithRightJoin\",\"url\":\"types/SelectQueryBuilderWithRightJoin.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"SelectQueryBuilderWithFullJoin\",\"url\":\"types/SelectQueryBuilderWithFullJoin.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":128,\"name\":\"InsertQueryBuilder\",\"url\":\"classes/InsertQueryBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/InsertQueryBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"values\",\"url\":\"classes/InsertQueryBuilder.html#values\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"columns\",\"url\":\"classes/InsertQueryBuilder.html#columns\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"expression\",\"url\":\"classes/InsertQueryBuilder.html#expression\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"ignore\",\"url\":\"classes/InsertQueryBuilder.html#ignore\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"onConflict\",\"url\":\"classes/InsertQueryBuilder.html#onConflict\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"onDuplicateKeyUpdate\",\"url\":\"classes/InsertQueryBuilder.html#onDuplicateKeyUpdate\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"returning\",\"url\":\"classes/InsertQueryBuilder.html#returning\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"returningAll\",\"url\":\"classes/InsertQueryBuilder.html#returningAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/InsertQueryBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"call\",\"url\":\"classes/InsertQueryBuilder.html#call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"$if\",\"url\":\"classes/InsertQueryBuilder.html#_if\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"if\",\"url\":\"classes/InsertQueryBuilder.html#if\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"$castTo\",\"url\":\"classes/InsertQueryBuilder.html#_castTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"castTo\",\"url\":\"classes/InsertQueryBuilder.html#castTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"$narrowType\",\"url\":\"classes/InsertQueryBuilder.html#_narrowType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"$assertType\",\"url\":\"classes/InsertQueryBuilder.html#_assertType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"assertType\",\"url\":\"classes/InsertQueryBuilder.html#assertType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"withPlugin\",\"url\":\"classes/InsertQueryBuilder.html#withPlugin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/InsertQueryBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/InsertQueryBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/InsertQueryBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"executeTakeFirst\",\"url\":\"classes/InsertQueryBuilder.html#executeTakeFirst\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"executeTakeFirstOrThrow\",\"url\":\"classes/InsertQueryBuilder.html#executeTakeFirstOrThrow\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"stream\",\"url\":\"classes/InsertQueryBuilder.html#stream\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":2048,\"name\":\"explain\",\"url\":\"classes/InsertQueryBuilder.html#explain\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"InsertQueryBuilder\"},{\"kind\":256,\"name\":\"InsertQueryBuilderProps\",\"url\":\"interfaces/InsertQueryBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/InsertQueryBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryBuilderProps\"},{\"kind\":1024,\"name\":\"queryNode\",\"url\":\"interfaces/InsertQueryBuilderProps.html#queryNode\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/InsertQueryBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryBuilderProps\"},{\"kind\":128,\"name\":\"UpdateQueryBuilder\",\"url\":\"classes/UpdateQueryBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/UpdateQueryBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"where\",\"url\":\"classes/UpdateQueryBuilder.html#where\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"whereRef\",\"url\":\"classes/UpdateQueryBuilder.html#whereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"orWhere\",\"url\":\"classes/UpdateQueryBuilder.html#orWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"orWhereRef\",\"url\":\"classes/UpdateQueryBuilder.html#orWhereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"whereExists\",\"url\":\"classes/UpdateQueryBuilder.html#whereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"whereNotExists\",\"url\":\"classes/UpdateQueryBuilder.html#whereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"orWhereExists\",\"url\":\"classes/UpdateQueryBuilder.html#orWhereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"orWhereNotExists\",\"url\":\"classes/UpdateQueryBuilder.html#orWhereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"clearWhere\",\"url\":\"classes/UpdateQueryBuilder.html#clearWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"from\",\"url\":\"classes/UpdateQueryBuilder.html#from\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"innerJoin\",\"url\":\"classes/UpdateQueryBuilder.html#innerJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"leftJoin\",\"url\":\"classes/UpdateQueryBuilder.html#leftJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"rightJoin\",\"url\":\"classes/UpdateQueryBuilder.html#rightJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"fullJoin\",\"url\":\"classes/UpdateQueryBuilder.html#fullJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"set\",\"url\":\"classes/UpdateQueryBuilder.html#set\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"returning\",\"url\":\"classes/UpdateQueryBuilder.html#returning\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"returningAll\",\"url\":\"classes/UpdateQueryBuilder.html#returningAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/UpdateQueryBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"call\",\"url\":\"classes/UpdateQueryBuilder.html#call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"$if\",\"url\":\"classes/UpdateQueryBuilder.html#_if\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"if\",\"url\":\"classes/UpdateQueryBuilder.html#if\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"$castTo\",\"url\":\"classes/UpdateQueryBuilder.html#_castTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"castTo\",\"url\":\"classes/UpdateQueryBuilder.html#castTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"$narrowType\",\"url\":\"classes/UpdateQueryBuilder.html#_narrowType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"$assertType\",\"url\":\"classes/UpdateQueryBuilder.html#_assertType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"assertType\",\"url\":\"classes/UpdateQueryBuilder.html#assertType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"withPlugin\",\"url\":\"classes/UpdateQueryBuilder.html#withPlugin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/UpdateQueryBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/UpdateQueryBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/UpdateQueryBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"executeTakeFirst\",\"url\":\"classes/UpdateQueryBuilder.html#executeTakeFirst\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"executeTakeFirstOrThrow\",\"url\":\"classes/UpdateQueryBuilder.html#executeTakeFirstOrThrow\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"stream\",\"url\":\"classes/UpdateQueryBuilder.html#stream\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":2048,\"name\":\"explain\",\"url\":\"classes/UpdateQueryBuilder.html#explain\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"UpdateQueryBuilder\"},{\"kind\":256,\"name\":\"UpdateQueryBuilderProps\",\"url\":\"interfaces/UpdateQueryBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/UpdateQueryBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UpdateQueryBuilderProps\"},{\"kind\":1024,\"name\":\"queryNode\",\"url\":\"interfaces/UpdateQueryBuilderProps.html#queryNode\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UpdateQueryBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/UpdateQueryBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UpdateQueryBuilderProps\"},{\"kind\":4194304,\"name\":\"UpdateQueryBuilderWithInnerJoin\",\"url\":\"types/UpdateQueryBuilderWithInnerJoin.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"UpdateQueryBuilderWithLeftJoin\",\"url\":\"types/UpdateQueryBuilderWithLeftJoin.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"UpdateQueryBuilderWithRightJoin\",\"url\":\"types/UpdateQueryBuilderWithRightJoin.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"UpdateQueryBuilderWithFullJoin\",\"url\":\"types/UpdateQueryBuilderWithFullJoin.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":128,\"name\":\"DeleteQueryBuilder\",\"url\":\"classes/DeleteQueryBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DeleteQueryBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"where\",\"url\":\"classes/DeleteQueryBuilder.html#where\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"whereRef\",\"url\":\"classes/DeleteQueryBuilder.html#whereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"orWhere\",\"url\":\"classes/DeleteQueryBuilder.html#orWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"orWhereRef\",\"url\":\"classes/DeleteQueryBuilder.html#orWhereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"whereExists\",\"url\":\"classes/DeleteQueryBuilder.html#whereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"whereNotExists\",\"url\":\"classes/DeleteQueryBuilder.html#whereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"orWhereExists\",\"url\":\"classes/DeleteQueryBuilder.html#orWhereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"orWhereNotExists\",\"url\":\"classes/DeleteQueryBuilder.html#orWhereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"clearWhere\",\"url\":\"classes/DeleteQueryBuilder.html#clearWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"using\",\"url\":\"classes/DeleteQueryBuilder.html#using\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"innerJoin\",\"url\":\"classes/DeleteQueryBuilder.html#innerJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"leftJoin\",\"url\":\"classes/DeleteQueryBuilder.html#leftJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"rightJoin\",\"url\":\"classes/DeleteQueryBuilder.html#rightJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"fullJoin\",\"url\":\"classes/DeleteQueryBuilder.html#fullJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"returning\",\"url\":\"classes/DeleteQueryBuilder.html#returning\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"returningAll\",\"url\":\"classes/DeleteQueryBuilder.html#returningAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"orderBy\",\"url\":\"classes/DeleteQueryBuilder.html#orderBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"limit\",\"url\":\"classes/DeleteQueryBuilder.html#limit\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/DeleteQueryBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"call\",\"url\":\"classes/DeleteQueryBuilder.html#call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"$if\",\"url\":\"classes/DeleteQueryBuilder.html#_if\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"if\",\"url\":\"classes/DeleteQueryBuilder.html#if\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"$castTo\",\"url\":\"classes/DeleteQueryBuilder.html#_castTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"castTo\",\"url\":\"classes/DeleteQueryBuilder.html#castTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"$narrowType\",\"url\":\"classes/DeleteQueryBuilder.html#_narrowType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"$assertType\",\"url\":\"classes/DeleteQueryBuilder.html#_assertType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"assertType\",\"url\":\"classes/DeleteQueryBuilder.html#assertType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"withPlugin\",\"url\":\"classes/DeleteQueryBuilder.html#withPlugin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/DeleteQueryBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/DeleteQueryBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/DeleteQueryBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"executeTakeFirst\",\"url\":\"classes/DeleteQueryBuilder.html#executeTakeFirst\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"executeTakeFirstOrThrow\",\"url\":\"classes/DeleteQueryBuilder.html#executeTakeFirstOrThrow\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"stream\",\"url\":\"classes/DeleteQueryBuilder.html#stream\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":2048,\"name\":\"explain\",\"url\":\"classes/DeleteQueryBuilder.html#explain\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeleteQueryBuilder\"},{\"kind\":256,\"name\":\"DeleteQueryBuilderProps\",\"url\":\"interfaces/DeleteQueryBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/DeleteQueryBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DeleteQueryBuilderProps\"},{\"kind\":1024,\"name\":\"queryNode\",\"url\":\"interfaces/DeleteQueryBuilderProps.html#queryNode\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DeleteQueryBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/DeleteQueryBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DeleteQueryBuilderProps\"},{\"kind\":4194304,\"name\":\"DeleteQueryBuilderWithInnerJoin\",\"url\":\"types/DeleteQueryBuilderWithInnerJoin.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"DeleteQueryBuilderWithLeftJoin\",\"url\":\"types/DeleteQueryBuilderWithLeftJoin.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"DeleteQueryBuilderWithRightJoin\",\"url\":\"types/DeleteQueryBuilderWithRightJoin.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"DeleteQueryBuilderWithFullJoin\",\"url\":\"types/DeleteQueryBuilderWithFullJoin.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":64,\"name\":\"isNoResultErrorConstructor\",\"url\":\"functions/isNoResultErrorConstructor.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":4194304,\"name\":\"NoResultErrorConstructor\",\"url\":\"types/NoResultErrorConstructor.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":512,\"name\":\"__type\",\"url\":\"types/NoResultErrorConstructor.html#__type\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-type-alias\",\"parent\":\"NoResultErrorConstructor\"},{\"kind\":128,\"name\":\"NoResultError\",\"url\":\"classes/NoResultError.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/NoResultError.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"NoResultError\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"classes/NoResultError.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"NoResultError\"},{\"kind\":128,\"name\":\"JoinBuilder\",\"url\":\"classes/JoinBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/JoinBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"JoinBuilder\"},{\"kind\":2048,\"name\":\"on\",\"url\":\"classes/JoinBuilder.html#on\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"JoinBuilder\"},{\"kind\":2048,\"name\":\"orOn\",\"url\":\"classes/JoinBuilder.html#orOn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"JoinBuilder\"},{\"kind\":2048,\"name\":\"onRef\",\"url\":\"classes/JoinBuilder.html#onRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"JoinBuilder\"},{\"kind\":2048,\"name\":\"orOnRef\",\"url\":\"classes/JoinBuilder.html#orOnRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"JoinBuilder\"},{\"kind\":2048,\"name\":\"onExists\",\"url\":\"classes/JoinBuilder.html#onExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"JoinBuilder\"},{\"kind\":2048,\"name\":\"onNotExists\",\"url\":\"classes/JoinBuilder.html#onNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"JoinBuilder\"},{\"kind\":2048,\"name\":\"orOnExists\",\"url\":\"classes/JoinBuilder.html#orOnExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"JoinBuilder\"},{\"kind\":2048,\"name\":\"orOnNotExists\",\"url\":\"classes/JoinBuilder.html#orOnNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"JoinBuilder\"},{\"kind\":2048,\"name\":\"onTrue\",\"url\":\"classes/JoinBuilder.html#onTrue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"JoinBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/JoinBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"JoinBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/JoinBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"JoinBuilder\"},{\"kind\":256,\"name\":\"JoinBuilderProps\",\"url\":\"interfaces/JoinBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"joinNode\",\"url\":\"interfaces/JoinBuilderProps.html#joinNode\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"JoinBuilderProps\"},{\"kind\":64,\"name\":\"createFunctionModule\",\"url\":\"functions/createFunctionModule.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":256,\"name\":\"FunctionModule\",\"url\":\"interfaces/FunctionModule.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"agg\",\"url\":\"interfaces/FunctionModule.html#agg\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"FunctionModule\"},{\"kind\":2048,\"name\":\"avg\",\"url\":\"interfaces/FunctionModule.html#avg\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"FunctionModule\"},{\"kind\":2048,\"name\":\"coalesce\",\"url\":\"interfaces/FunctionModule.html#coalesce\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"FunctionModule\"},{\"kind\":2048,\"name\":\"count\",\"url\":\"interfaces/FunctionModule.html#count\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"FunctionModule\"},{\"kind\":2048,\"name\":\"countAll\",\"url\":\"interfaces/FunctionModule.html#countAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"FunctionModule\"},{\"kind\":2048,\"name\":\"max\",\"url\":\"interfaces/FunctionModule.html#max\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"FunctionModule\"},{\"kind\":2048,\"name\":\"min\",\"url\":\"interfaces/FunctionModule.html#min\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"FunctionModule\"},{\"kind\":2048,\"name\":\"sum\",\"url\":\"interfaces/FunctionModule.html#sum\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"FunctionModule\"},{\"kind\":128,\"name\":\"InsertResult\",\"url\":\"classes/InsertResult.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/InsertResult.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"InsertResult\"},{\"kind\":262144,\"name\":\"insertId\",\"url\":\"classes/InsertResult.html#insertId\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"InsertResult\"},{\"kind\":262144,\"name\":\"numInsertedOrUpdatedRows\",\"url\":\"classes/InsertResult.html#numInsertedOrUpdatedRows\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"InsertResult\"},{\"kind\":128,\"name\":\"DeleteResult\",\"url\":\"classes/DeleteResult.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DeleteResult.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"DeleteResult\"},{\"kind\":262144,\"name\":\"numDeletedRows\",\"url\":\"classes/DeleteResult.html#numDeletedRows\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"DeleteResult\"},{\"kind\":128,\"name\":\"UpdateResult\",\"url\":\"classes/UpdateResult.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/UpdateResult.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"UpdateResult\"},{\"kind\":262144,\"name\":\"numUpdatedRows\",\"url\":\"classes/UpdateResult.html#numUpdatedRows\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"UpdateResult\"},{\"kind\":128,\"name\":\"OnConflictBuilder\",\"url\":\"classes/OnConflictBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/OnConflictBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"column\",\"url\":\"classes/OnConflictBuilder.html#column\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"columns\",\"url\":\"classes/OnConflictBuilder.html#columns\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"constraint\",\"url\":\"classes/OnConflictBuilder.html#constraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"expression\",\"url\":\"classes/OnConflictBuilder.html#expression\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"where\",\"url\":\"classes/OnConflictBuilder.html#where\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"whereRef\",\"url\":\"classes/OnConflictBuilder.html#whereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"orWhere\",\"url\":\"classes/OnConflictBuilder.html#orWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"orWhereRef\",\"url\":\"classes/OnConflictBuilder.html#orWhereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"whereExists\",\"url\":\"classes/OnConflictBuilder.html#whereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"whereNotExists\",\"url\":\"classes/OnConflictBuilder.html#whereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"orWhereExists\",\"url\":\"classes/OnConflictBuilder.html#orWhereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"orWhereNotExists\",\"url\":\"classes/OnConflictBuilder.html#orWhereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"clearWhere\",\"url\":\"classes/OnConflictBuilder.html#clearWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"doNothing\",\"url\":\"classes/OnConflictBuilder.html#doNothing\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"doUpdateSet\",\"url\":\"classes/OnConflictBuilder.html#doUpdateSet\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/OnConflictBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictBuilder\"},{\"kind\":256,\"name\":\"OnConflictBuilderProps\",\"url\":\"interfaces/OnConflictBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"onConflictNode\",\"url\":\"interfaces/OnConflictBuilderProps.html#onConflictNode\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OnConflictBuilderProps\"},{\"kind\":4194304,\"name\":\"OnConflictDatabase\",\"url\":\"types/OnConflictDatabase.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"OnConflictTables\",\"url\":\"types/OnConflictTables.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":128,\"name\":\"OnConflictDoNothingBuilder\",\"url\":\"classes/OnConflictDoNothingBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/OnConflictDoNothingBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"OnConflictDoNothingBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/OnConflictDoNothingBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictDoNothingBuilder\"},{\"kind\":128,\"name\":\"OnConflictUpdateBuilder\",\"url\":\"classes/OnConflictUpdateBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/OnConflictUpdateBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"OnConflictUpdateBuilder\"},{\"kind\":2048,\"name\":\"where\",\"url\":\"classes/OnConflictUpdateBuilder.html#where\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictUpdateBuilder\"},{\"kind\":2048,\"name\":\"whereRef\",\"url\":\"classes/OnConflictUpdateBuilder.html#whereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictUpdateBuilder\"},{\"kind\":2048,\"name\":\"orWhere\",\"url\":\"classes/OnConflictUpdateBuilder.html#orWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictUpdateBuilder\"},{\"kind\":2048,\"name\":\"orWhereRef\",\"url\":\"classes/OnConflictUpdateBuilder.html#orWhereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictUpdateBuilder\"},{\"kind\":2048,\"name\":\"whereExists\",\"url\":\"classes/OnConflictUpdateBuilder.html#whereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictUpdateBuilder\"},{\"kind\":2048,\"name\":\"whereNotExists\",\"url\":\"classes/OnConflictUpdateBuilder.html#whereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictUpdateBuilder\"},{\"kind\":2048,\"name\":\"orWhereExists\",\"url\":\"classes/OnConflictUpdateBuilder.html#orWhereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictUpdateBuilder\"},{\"kind\":2048,\"name\":\"orWhereNotExists\",\"url\":\"classes/OnConflictUpdateBuilder.html#orWhereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictUpdateBuilder\"},{\"kind\":2048,\"name\":\"clearWhere\",\"url\":\"classes/OnConflictUpdateBuilder.html#clearWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictUpdateBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/OnConflictUpdateBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictUpdateBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/OnConflictUpdateBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OnConflictUpdateBuilder\"},{\"kind\":128,\"name\":\"AggregateFunctionBuilder\",\"url\":\"classes/AggregateFunctionBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/AggregateFunctionBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"as\",\"url\":\"classes/AggregateFunctionBuilder.html#as\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"distinct\",\"url\":\"classes/AggregateFunctionBuilder.html#distinct\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"filterWhere\",\"url\":\"classes/AggregateFunctionBuilder.html#filterWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"filterWhereExists\",\"url\":\"classes/AggregateFunctionBuilder.html#filterWhereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"filterWhereNotExists\",\"url\":\"classes/AggregateFunctionBuilder.html#filterWhereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"filterWhereRef\",\"url\":\"classes/AggregateFunctionBuilder.html#filterWhereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"orFilterWhere\",\"url\":\"classes/AggregateFunctionBuilder.html#orFilterWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"orFilterWhereExists\",\"url\":\"classes/AggregateFunctionBuilder.html#orFilterWhereExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"orFilterWhereNotExists\",\"url\":\"classes/AggregateFunctionBuilder.html#orFilterWhereNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"orFilterWhereRef\",\"url\":\"classes/AggregateFunctionBuilder.html#orFilterWhereRef\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"over\",\"url\":\"classes/AggregateFunctionBuilder.html#over\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/AggregateFunctionBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/AggregateFunctionBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AggregateFunctionBuilder\"},{\"kind\":128,\"name\":\"AliasedAggregateFunctionBuilder\",\"url\":\"classes/AliasedAggregateFunctionBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/AliasedAggregateFunctionBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"AliasedAggregateFunctionBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/AliasedAggregateFunctionBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AliasedAggregateFunctionBuilder\"},{\"kind\":256,\"name\":\"AggregateFunctionBuilderProps\",\"url\":\"interfaces/AggregateFunctionBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"aggregateFunctionNode\",\"url\":\"interfaces/AggregateFunctionBuilderProps.html#aggregateFunctionNode\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AggregateFunctionBuilderProps\"},{\"kind\":4194304,\"name\":\"OverBuilderCallback\",\"url\":\"types/OverBuilderCallback.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/OverBuilderCallback.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"OverBuilderCallback\"},{\"kind\":128,\"name\":\"CaseBuilder\",\"url\":\"classes/CaseBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/CaseBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"CaseBuilder\"},{\"kind\":2048,\"name\":\"when\",\"url\":\"classes/CaseBuilder.html#when\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CaseBuilder\"},{\"kind\":128,\"name\":\"CaseThenBuilder\",\"url\":\"classes/CaseThenBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/CaseThenBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"CaseThenBuilder\"},{\"kind\":2048,\"name\":\"then\",\"url\":\"classes/CaseThenBuilder.html#then\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CaseThenBuilder\"},{\"kind\":128,\"name\":\"CaseWhenBuilder\",\"url\":\"classes/CaseWhenBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/CaseWhenBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"CaseWhenBuilder\"},{\"kind\":2048,\"name\":\"when\",\"url\":\"classes/CaseWhenBuilder.html#when\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CaseWhenBuilder\"},{\"kind\":2048,\"name\":\"else\",\"url\":\"classes/CaseWhenBuilder.html#else\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CaseWhenBuilder\"},{\"kind\":2048,\"name\":\"end\",\"url\":\"classes/CaseWhenBuilder.html#end\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CaseWhenBuilder\"},{\"kind\":2048,\"name\":\"endCase\",\"url\":\"classes/CaseWhenBuilder.html#endCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CaseWhenBuilder\"},{\"kind\":128,\"name\":\"CaseEndBuilder\",\"url\":\"classes/CaseEndBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/CaseEndBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"CaseEndBuilder\"},{\"kind\":2048,\"name\":\"end\",\"url\":\"classes/CaseEndBuilder.html#end\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CaseEndBuilder\"},{\"kind\":2048,\"name\":\"endCase\",\"url\":\"classes/CaseEndBuilder.html#endCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CaseEndBuilder\"},{\"kind\":64,\"name\":\"isRawBuilder\",\"url\":\"functions/isRawBuilder.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":128,\"name\":\"RawBuilder\",\"url\":\"classes/RawBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/RawBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"RawBuilder\"},{\"kind\":2048,\"name\":\"as\",\"url\":\"classes/RawBuilder.html#as\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"RawBuilder\"},{\"kind\":2048,\"name\":\"$castTo\",\"url\":\"classes/RawBuilder.html#_castTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"RawBuilder\"},{\"kind\":2048,\"name\":\"castTo\",\"url\":\"classes/RawBuilder.html#castTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"RawBuilder\"},{\"kind\":2048,\"name\":\"withPlugin\",\"url\":\"classes/RawBuilder.html#withPlugin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"RawBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/RawBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"RawBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/RawBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"RawBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/RawBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"RawBuilder\"},{\"kind\":128,\"name\":\"AliasedRawBuilder\",\"url\":\"classes/AliasedRawBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/AliasedRawBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"AliasedRawBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/AliasedRawBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AliasedRawBuilder\"},{\"kind\":256,\"name\":\"RawBuilderProps\",\"url\":\"interfaces/RawBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/RawBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"RawBuilderProps\"},{\"kind\":1024,\"name\":\"rawNode\",\"url\":\"interfaces/RawBuilderProps.html#rawNode\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"RawBuilderProps\"},{\"kind\":1024,\"name\":\"plugins\",\"url\":\"interfaces/RawBuilderProps.html#plugins\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"RawBuilderProps\"},{\"kind\":256,\"name\":\"Sql\",\"url\":\"interfaces/Sql.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"val\",\"url\":\"interfaces/Sql.html#val\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Sql\"},{\"kind\":2048,\"name\":\"value\",\"url\":\"interfaces/Sql.html#value\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Sql\"},{\"kind\":2048,\"name\":\"ref\",\"url\":\"interfaces/Sql.html#ref\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Sql\"},{\"kind\":2048,\"name\":\"table\",\"url\":\"interfaces/Sql.html#table\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Sql\"},{\"kind\":2048,\"name\":\"id\",\"url\":\"interfaces/Sql.html#id\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Sql\"},{\"kind\":2048,\"name\":\"lit\",\"url\":\"interfaces/Sql.html#lit\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Sql\"},{\"kind\":2048,\"name\":\"literal\",\"url\":\"interfaces/Sql.html#literal\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Sql\"},{\"kind\":2048,\"name\":\"raw\",\"url\":\"interfaces/Sql.html#raw\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Sql\"},{\"kind\":2048,\"name\":\"join\",\"url\":\"interfaces/Sql.html#join\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Sql\"},{\"kind\":64,\"name\":\"sql\",\"url\":\"functions/sql-1.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":256,\"name\":\"QueryExecutor\",\"url\":\"interfaces/QueryExecutor.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":262144,\"name\":\"adapter\",\"url\":\"interfaces/QueryExecutor.html#adapter\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-interface\",\"parent\":\"QueryExecutor\"},{\"kind\":262144,\"name\":\"plugins\",\"url\":\"interfaces/QueryExecutor.html#plugins\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-interface\",\"parent\":\"QueryExecutor\"},{\"kind\":2048,\"name\":\"transformQuery\",\"url\":\"interfaces/QueryExecutor.html#transformQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"QueryExecutor\"},{\"kind\":2048,\"name\":\"compileQuery\",\"url\":\"interfaces/QueryExecutor.html#compileQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"QueryExecutor\"},{\"kind\":2048,\"name\":\"executeQuery\",\"url\":\"interfaces/QueryExecutor.html#executeQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"QueryExecutor\"},{\"kind\":2048,\"name\":\"stream\",\"url\":\"interfaces/QueryExecutor.html#stream\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"QueryExecutor\"},{\"kind\":2048,\"name\":\"withConnectionProvider\",\"url\":\"interfaces/QueryExecutor.html#withConnectionProvider\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"QueryExecutor\"},{\"kind\":2048,\"name\":\"withPlugin\",\"url\":\"interfaces/QueryExecutor.html#withPlugin\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"QueryExecutor\"},{\"kind\":2048,\"name\":\"withPlugins\",\"url\":\"interfaces/QueryExecutor.html#withPlugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"QueryExecutor\"},{\"kind\":2048,\"name\":\"withPluginAtFront\",\"url\":\"interfaces/QueryExecutor.html#withPluginAtFront\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"QueryExecutor\"},{\"kind\":2048,\"name\":\"withoutPlugins\",\"url\":\"interfaces/QueryExecutor.html#withoutPlugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"QueryExecutor\"},{\"kind\":2048,\"name\":\"provideConnection\",\"url\":\"interfaces/QueryExecutor.html#provideConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface tsd-is-inherited\",\"parent\":\"QueryExecutor\"},{\"kind\":128,\"name\":\"DefaultQueryExecutor\",\"url\":\"classes/DefaultQueryExecutor.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DefaultQueryExecutor.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"DefaultQueryExecutor\"},{\"kind\":262144,\"name\":\"adapter\",\"url\":\"classes/DefaultQueryExecutor.html#adapter\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"DefaultQueryExecutor\"},{\"kind\":2048,\"name\":\"compileQuery\",\"url\":\"classes/DefaultQueryExecutor.html#compileQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DefaultQueryExecutor\"},{\"kind\":2048,\"name\":\"provideConnection\",\"url\":\"classes/DefaultQueryExecutor.html#provideConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DefaultQueryExecutor\"},{\"kind\":2048,\"name\":\"withPlugins\",\"url\":\"classes/DefaultQueryExecutor.html#withPlugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DefaultQueryExecutor\"},{\"kind\":2048,\"name\":\"withPlugin\",\"url\":\"classes/DefaultQueryExecutor.html#withPlugin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DefaultQueryExecutor\"},{\"kind\":2048,\"name\":\"withPluginAtFront\",\"url\":\"classes/DefaultQueryExecutor.html#withPluginAtFront\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DefaultQueryExecutor\"},{\"kind\":2048,\"name\":\"withConnectionProvider\",\"url\":\"classes/DefaultQueryExecutor.html#withConnectionProvider\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DefaultQueryExecutor\"},{\"kind\":2048,\"name\":\"withoutPlugins\",\"url\":\"classes/DefaultQueryExecutor.html#withoutPlugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DefaultQueryExecutor\"},{\"kind\":262144,\"name\":\"plugins\",\"url\":\"classes/DefaultQueryExecutor.html#plugins\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"DefaultQueryExecutor\"},{\"kind\":2048,\"name\":\"transformQuery\",\"url\":\"classes/DefaultQueryExecutor.html#transformQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"DefaultQueryExecutor\"},{\"kind\":2048,\"name\":\"executeQuery\",\"url\":\"classes/DefaultQueryExecutor.html#executeQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"DefaultQueryExecutor\"},{\"kind\":2048,\"name\":\"stream\",\"url\":\"classes/DefaultQueryExecutor.html#stream\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"DefaultQueryExecutor\"},{\"kind\":128,\"name\":\"NoopQueryExecutor\",\"url\":\"classes/NoopQueryExecutor.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/NoopQueryExecutor.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"NoopQueryExecutor\"},{\"kind\":262144,\"name\":\"adapter\",\"url\":\"classes/NoopQueryExecutor.html#adapter\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"NoopQueryExecutor\"},{\"kind\":2048,\"name\":\"compileQuery\",\"url\":\"classes/NoopQueryExecutor.html#compileQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"NoopQueryExecutor\"},{\"kind\":2048,\"name\":\"provideConnection\",\"url\":\"classes/NoopQueryExecutor.html#provideConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"NoopQueryExecutor\"},{\"kind\":2048,\"name\":\"withConnectionProvider\",\"url\":\"classes/NoopQueryExecutor.html#withConnectionProvider\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"NoopQueryExecutor\"},{\"kind\":2048,\"name\":\"withPlugin\",\"url\":\"classes/NoopQueryExecutor.html#withPlugin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"NoopQueryExecutor\"},{\"kind\":2048,\"name\":\"withPlugins\",\"url\":\"classes/NoopQueryExecutor.html#withPlugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"NoopQueryExecutor\"},{\"kind\":2048,\"name\":\"withPluginAtFront\",\"url\":\"classes/NoopQueryExecutor.html#withPluginAtFront\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"NoopQueryExecutor\"},{\"kind\":2048,\"name\":\"withoutPlugins\",\"url\":\"classes/NoopQueryExecutor.html#withoutPlugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"NoopQueryExecutor\"},{\"kind\":262144,\"name\":\"plugins\",\"url\":\"classes/NoopQueryExecutor.html#plugins\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"NoopQueryExecutor\"},{\"kind\":2048,\"name\":\"transformQuery\",\"url\":\"classes/NoopQueryExecutor.html#transformQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"NoopQueryExecutor\"},{\"kind\":2048,\"name\":\"executeQuery\",\"url\":\"classes/NoopQueryExecutor.html#executeQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"NoopQueryExecutor\"},{\"kind\":2048,\"name\":\"stream\",\"url\":\"classes/NoopQueryExecutor.html#stream\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"NoopQueryExecutor\"},{\"kind\":32,\"name\":\"NOOP_QUERY_EXECUTOR\",\"url\":\"variables/NOOP_QUERY_EXECUTOR.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":128,\"name\":\"DefaultQueryCompiler\",\"url\":\"classes/DefaultQueryCompiler.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DefaultQueryCompiler.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":262144,\"name\":\"numParameters\",\"url\":\"classes/DefaultQueryCompiler.html#numParameters\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"compileQuery\",\"url\":\"classes/DefaultQueryCompiler.html#compileQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"getSql\",\"url\":\"classes/DefaultQueryCompiler.html#getSql\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelectQuery\",\"url\":\"classes/DefaultQueryCompiler.html#visitSelectQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitFrom\",\"url\":\"classes/DefaultQueryCompiler.html#visitFrom\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelection\",\"url\":\"classes/DefaultQueryCompiler.html#visitSelection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitColumn\",\"url\":\"classes/DefaultQueryCompiler.html#visitColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"compileDistinctOn\",\"url\":\"classes/DefaultQueryCompiler.html#compileDistinctOn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"compileList\",\"url\":\"classes/DefaultQueryCompiler.html#compileList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitWhere\",\"url\":\"classes/DefaultQueryCompiler.html#visitWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitHaving\",\"url\":\"classes/DefaultQueryCompiler.html#visitHaving\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitInsertQuery\",\"url\":\"classes/DefaultQueryCompiler.html#visitInsertQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitValues\",\"url\":\"classes/DefaultQueryCompiler.html#visitValues\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDeleteQuery\",\"url\":\"classes/DefaultQueryCompiler.html#visitDeleteQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitReturning\",\"url\":\"classes/DefaultQueryCompiler.html#visitReturning\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAlias\",\"url\":\"classes/DefaultQueryCompiler.html#visitAlias\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitReference\",\"url\":\"classes/DefaultQueryCompiler.html#visitReference\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelectAll\",\"url\":\"classes/DefaultQueryCompiler.html#visitSelectAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitIdentifier\",\"url\":\"classes/DefaultQueryCompiler.html#visitIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"compileUnwrappedIdentifier\",\"url\":\"classes/DefaultQueryCompiler.html#compileUnwrappedIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAnd\",\"url\":\"classes/DefaultQueryCompiler.html#visitAnd\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOr\",\"url\":\"classes/DefaultQueryCompiler.html#visitOr\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitValue\",\"url\":\"classes/DefaultQueryCompiler.html#visitValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitValueList\",\"url\":\"classes/DefaultQueryCompiler.html#visitValueList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPrimitiveValueList\",\"url\":\"classes/DefaultQueryCompiler.html#visitPrimitiveValueList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitParens\",\"url\":\"classes/DefaultQueryCompiler.html#visitParens\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitJoin\",\"url\":\"classes/DefaultQueryCompiler.html#visitJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOn\",\"url\":\"classes/DefaultQueryCompiler.html#visitOn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitRaw\",\"url\":\"classes/DefaultQueryCompiler.html#visitRaw\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOperator\",\"url\":\"classes/DefaultQueryCompiler.html#visitOperator\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitTable\",\"url\":\"classes/DefaultQueryCompiler.html#visitTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSchemableIdentifier\",\"url\":\"classes/DefaultQueryCompiler.html#visitSchemableIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateTable\",\"url\":\"classes/DefaultQueryCompiler.html#visitCreateTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitColumnDefinition\",\"url\":\"classes/DefaultQueryCompiler.html#visitColumnDefinition\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"getAutoIncrement\",\"url\":\"classes/DefaultQueryCompiler.html#getAutoIncrement\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitReferences\",\"url\":\"classes/DefaultQueryCompiler.html#visitReferences\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropTable\",\"url\":\"classes/DefaultQueryCompiler.html#visitDropTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDataType\",\"url\":\"classes/DefaultQueryCompiler.html#visitDataType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOrderBy\",\"url\":\"classes/DefaultQueryCompiler.html#visitOrderBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOrderByItem\",\"url\":\"classes/DefaultQueryCompiler.html#visitOrderByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitGroupBy\",\"url\":\"classes/DefaultQueryCompiler.html#visitGroupBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitGroupByItem\",\"url\":\"classes/DefaultQueryCompiler.html#visitGroupByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUpdateQuery\",\"url\":\"classes/DefaultQueryCompiler.html#visitUpdateQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitColumnUpdate\",\"url\":\"classes/DefaultQueryCompiler.html#visitColumnUpdate\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitLimit\",\"url\":\"classes/DefaultQueryCompiler.html#visitLimit\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOffset\",\"url\":\"classes/DefaultQueryCompiler.html#visitOffset\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOnConflict\",\"url\":\"classes/DefaultQueryCompiler.html#visitOnConflict\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOnDuplicateKey\",\"url\":\"classes/DefaultQueryCompiler.html#visitOnDuplicateKey\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateIndex\",\"url\":\"classes/DefaultQueryCompiler.html#visitCreateIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropIndex\",\"url\":\"classes/DefaultQueryCompiler.html#visitDropIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateSchema\",\"url\":\"classes/DefaultQueryCompiler.html#visitCreateSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropSchema\",\"url\":\"classes/DefaultQueryCompiler.html#visitDropSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPrimaryKeyConstraint\",\"url\":\"classes/DefaultQueryCompiler.html#visitPrimaryKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUniqueConstraint\",\"url\":\"classes/DefaultQueryCompiler.html#visitUniqueConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCheckConstraint\",\"url\":\"classes/DefaultQueryCompiler.html#visitCheckConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitForeignKeyConstraint\",\"url\":\"classes/DefaultQueryCompiler.html#visitForeignKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitList\",\"url\":\"classes/DefaultQueryCompiler.html#visitList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitWith\",\"url\":\"classes/DefaultQueryCompiler.html#visitWith\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCommonTableExpression\",\"url\":\"classes/DefaultQueryCompiler.html#visitCommonTableExpression\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCommonTableExpressionName\",\"url\":\"classes/DefaultQueryCompiler.html#visitCommonTableExpressionName\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAlterTable\",\"url\":\"classes/DefaultQueryCompiler.html#visitAlterTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAddColumn\",\"url\":\"classes/DefaultQueryCompiler.html#visitAddColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitRenameColumn\",\"url\":\"classes/DefaultQueryCompiler.html#visitRenameColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropColumn\",\"url\":\"classes/DefaultQueryCompiler.html#visitDropColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAlterColumn\",\"url\":\"classes/DefaultQueryCompiler.html#visitAlterColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitModifyColumn\",\"url\":\"classes/DefaultQueryCompiler.html#visitModifyColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAddConstraint\",\"url\":\"classes/DefaultQueryCompiler.html#visitAddConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropConstraint\",\"url\":\"classes/DefaultQueryCompiler.html#visitDropConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSetOperation\",\"url\":\"classes/DefaultQueryCompiler.html#visitSetOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateView\",\"url\":\"classes/DefaultQueryCompiler.html#visitCreateView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropView\",\"url\":\"classes/DefaultQueryCompiler.html#visitDropView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitGenerated\",\"url\":\"classes/DefaultQueryCompiler.html#visitGenerated\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDefaultValue\",\"url\":\"classes/DefaultQueryCompiler.html#visitDefaultValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelectModifier\",\"url\":\"classes/DefaultQueryCompiler.html#visitSelectModifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateType\",\"url\":\"classes/DefaultQueryCompiler.html#visitCreateType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropType\",\"url\":\"classes/DefaultQueryCompiler.html#visitDropType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitExplain\",\"url\":\"classes/DefaultQueryCompiler.html#visitExplain\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDefaultInsertValue\",\"url\":\"classes/DefaultQueryCompiler.html#visitDefaultInsertValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAggregateFunction\",\"url\":\"classes/DefaultQueryCompiler.html#visitAggregateFunction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOver\",\"url\":\"classes/DefaultQueryCompiler.html#visitOver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPartitionBy\",\"url\":\"classes/DefaultQueryCompiler.html#visitPartitionBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPartitionByItem\",\"url\":\"classes/DefaultQueryCompiler.html#visitPartitionByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitBinaryOperation\",\"url\":\"classes/DefaultQueryCompiler.html#visitBinaryOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUnaryOperation\",\"url\":\"classes/DefaultQueryCompiler.html#visitUnaryOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"isMinusOperator\",\"url\":\"classes/DefaultQueryCompiler.html#isMinusOperator\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUsing\",\"url\":\"classes/DefaultQueryCompiler.html#visitUsing\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitFunction\",\"url\":\"classes/DefaultQueryCompiler.html#visitFunction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCase\",\"url\":\"classes/DefaultQueryCompiler.html#visitCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitWhen\",\"url\":\"classes/DefaultQueryCompiler.html#visitWhen\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"append\",\"url\":\"classes/DefaultQueryCompiler.html#append\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"appendValue\",\"url\":\"classes/DefaultQueryCompiler.html#appendValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"getLeftIdentifierWrapper\",\"url\":\"classes/DefaultQueryCompiler.html#getLeftIdentifierWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"getRightIdentifierWrapper\",\"url\":\"classes/DefaultQueryCompiler.html#getRightIdentifierWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"getCurrentParameterPlaceholder\",\"url\":\"classes/DefaultQueryCompiler.html#getCurrentParameterPlaceholder\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"getLeftExplainOptionsWrapper\",\"url\":\"classes/DefaultQueryCompiler.html#getLeftExplainOptionsWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"getExplainOptionAssignment\",\"url\":\"classes/DefaultQueryCompiler.html#getExplainOptionAssignment\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"getExplainOptionsDelimiter\",\"url\":\"classes/DefaultQueryCompiler.html#getExplainOptionsDelimiter\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"getRightExplainOptionsWrapper\",\"url\":\"classes/DefaultQueryCompiler.html#getRightExplainOptionsWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"sanitizeIdentifier\",\"url\":\"classes/DefaultQueryCompiler.html#sanitizeIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"addParameter\",\"url\":\"classes/DefaultQueryCompiler.html#addParameter\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"appendImmediateValue\",\"url\":\"classes/DefaultQueryCompiler.html#appendImmediateValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":1024,\"name\":\"nodeStack\",\"url\":\"classes/DefaultQueryCompiler.html#nodeStack\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":262144,\"name\":\"parentNode\",\"url\":\"classes/DefaultQueryCompiler.html#parentNode\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":2048,\"name\":\"visitNode\",\"url\":\"classes/DefaultQueryCompiler.html#visitNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"DefaultQueryCompiler\"},{\"kind\":32,\"name\":\"CompiledQuery\",\"url\":\"variables/CompiledQuery-1.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":256,\"name\":\"CompiledQuery\",\"url\":\"interfaces/CompiledQuery.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"query\",\"url\":\"interfaces/CompiledQuery.html#query\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CompiledQuery\"},{\"kind\":1024,\"name\":\"sql\",\"url\":\"interfaces/CompiledQuery.html#sql\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CompiledQuery\"},{\"kind\":1024,\"name\":\"parameters\",\"url\":\"interfaces/CompiledQuery.html#parameters\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CompiledQuery\"},{\"kind\":128,\"name\":\"SchemaModule\",\"url\":\"classes/SchemaModule.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/SchemaModule.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"createTable\",\"url\":\"classes/SchemaModule.html#createTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"dropTable\",\"url\":\"classes/SchemaModule.html#dropTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"createIndex\",\"url\":\"classes/SchemaModule.html#createIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"dropIndex\",\"url\":\"classes/SchemaModule.html#dropIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"createSchema\",\"url\":\"classes/SchemaModule.html#createSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"dropSchema\",\"url\":\"classes/SchemaModule.html#dropSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"alterTable\",\"url\":\"classes/SchemaModule.html#alterTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"createView\",\"url\":\"classes/SchemaModule.html#createView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"dropView\",\"url\":\"classes/SchemaModule.html#dropView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"createType\",\"url\":\"classes/SchemaModule.html#createType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"dropType\",\"url\":\"classes/SchemaModule.html#dropType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"withPlugin\",\"url\":\"classes/SchemaModule.html#withPlugin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"withoutPlugins\",\"url\":\"classes/SchemaModule.html#withoutPlugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":2048,\"name\":\"withSchema\",\"url\":\"classes/SchemaModule.html#withSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SchemaModule\"},{\"kind\":128,\"name\":\"CreateTableBuilder\",\"url\":\"classes/CreateTableBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/CreateTableBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"temporary\",\"url\":\"classes/CreateTableBuilder.html#temporary\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"onCommit\",\"url\":\"classes/CreateTableBuilder.html#onCommit\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"ifNotExists\",\"url\":\"classes/CreateTableBuilder.html#ifNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"addColumn\",\"url\":\"classes/CreateTableBuilder.html#addColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"addPrimaryKeyConstraint\",\"url\":\"classes/CreateTableBuilder.html#addPrimaryKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"addUniqueConstraint\",\"url\":\"classes/CreateTableBuilder.html#addUniqueConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"addCheckConstraint\",\"url\":\"classes/CreateTableBuilder.html#addCheckConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"addForeignKeyConstraint\",\"url\":\"classes/CreateTableBuilder.html#addForeignKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"modifyFront\",\"url\":\"classes/CreateTableBuilder.html#modifyFront\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"modifyEnd\",\"url\":\"classes/CreateTableBuilder.html#modifyEnd\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/CreateTableBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"call\",\"url\":\"classes/CreateTableBuilder.html#call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/CreateTableBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/CreateTableBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/CreateTableBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTableBuilder\"},{\"kind\":256,\"name\":\"CreateTableBuilderProps\",\"url\":\"interfaces/CreateTableBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/CreateTableBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTableBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/CreateTableBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTableBuilderProps\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/CreateTableBuilderProps.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTableBuilderProps\"},{\"kind\":4194304,\"name\":\"ColumnBuilderCallback\",\"url\":\"types/ColumnBuilderCallback.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/ColumnBuilderCallback.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"ColumnBuilderCallback\"},{\"kind\":4194304,\"name\":\"ForeignKeyConstraintBuilderCallback\",\"url\":\"types/ForeignKeyConstraintBuilderCallback.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/ForeignKeyConstraintBuilderCallback.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"ForeignKeyConstraintBuilderCallback\"},{\"kind\":128,\"name\":\"CreateTypeBuilder\",\"url\":\"classes/CreateTypeBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/CreateTypeBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"CreateTypeBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/CreateTypeBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTypeBuilder\"},{\"kind\":2048,\"name\":\"asEnum\",\"url\":\"classes/CreateTypeBuilder.html#asEnum\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTypeBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/CreateTypeBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTypeBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/CreateTypeBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTypeBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/CreateTypeBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateTypeBuilder\"},{\"kind\":256,\"name\":\"CreateTypeBuilderProps\",\"url\":\"interfaces/CreateTypeBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/CreateTypeBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTypeBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/CreateTypeBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTypeBuilderProps\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/CreateTypeBuilderProps.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTypeBuilderProps\"},{\"kind\":128,\"name\":\"DropTableBuilder\",\"url\":\"classes/DropTableBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DropTableBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"DropTableBuilder\"},{\"kind\":2048,\"name\":\"ifExists\",\"url\":\"classes/DropTableBuilder.html#ifExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropTableBuilder\"},{\"kind\":2048,\"name\":\"cascade\",\"url\":\"classes/DropTableBuilder.html#cascade\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropTableBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/DropTableBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropTableBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/DropTableBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropTableBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/DropTableBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropTableBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/DropTableBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropTableBuilder\"},{\"kind\":256,\"name\":\"DropTableBuilderProps\",\"url\":\"interfaces/DropTableBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/DropTableBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropTableBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/DropTableBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropTableBuilderProps\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/DropTableBuilderProps.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropTableBuilderProps\"},{\"kind\":128,\"name\":\"DropTypeBuilder\",\"url\":\"classes/DropTypeBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DropTypeBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"DropTypeBuilder\"},{\"kind\":2048,\"name\":\"ifExists\",\"url\":\"classes/DropTypeBuilder.html#ifExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropTypeBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/DropTypeBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropTypeBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/DropTypeBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropTypeBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/DropTypeBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropTypeBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/DropTypeBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropTypeBuilder\"},{\"kind\":256,\"name\":\"DropTypeBuilderProps\",\"url\":\"interfaces/DropTypeBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/DropTypeBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropTypeBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/DropTypeBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropTypeBuilderProps\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/DropTypeBuilderProps.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropTypeBuilderProps\"},{\"kind\":128,\"name\":\"CreateIndexBuilder\",\"url\":\"classes/CreateIndexBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/CreateIndexBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"CreateIndexBuilder\"},{\"kind\":2048,\"name\":\"ifNotExists\",\"url\":\"classes/CreateIndexBuilder.html#ifNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateIndexBuilder\"},{\"kind\":2048,\"name\":\"unique\",\"url\":\"classes/CreateIndexBuilder.html#unique\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateIndexBuilder\"},{\"kind\":2048,\"name\":\"on\",\"url\":\"classes/CreateIndexBuilder.html#on\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateIndexBuilder\"},{\"kind\":2048,\"name\":\"column\",\"url\":\"classes/CreateIndexBuilder.html#column\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateIndexBuilder\"},{\"kind\":2048,\"name\":\"columns\",\"url\":\"classes/CreateIndexBuilder.html#columns\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateIndexBuilder\"},{\"kind\":2048,\"name\":\"expression\",\"url\":\"classes/CreateIndexBuilder.html#expression\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateIndexBuilder\"},{\"kind\":2048,\"name\":\"using\",\"url\":\"classes/CreateIndexBuilder.html#using\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateIndexBuilder\"},{\"kind\":2048,\"name\":\"where\",\"url\":\"classes/CreateIndexBuilder.html#where\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateIndexBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/CreateIndexBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateIndexBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/CreateIndexBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateIndexBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/CreateIndexBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateIndexBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/CreateIndexBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateIndexBuilder\"},{\"kind\":256,\"name\":\"CreateIndexBuilderProps\",\"url\":\"interfaces/CreateIndexBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/CreateIndexBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateIndexBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/CreateIndexBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateIndexBuilderProps\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/CreateIndexBuilderProps.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateIndexBuilderProps\"},{\"kind\":128,\"name\":\"DropIndexBuilder\",\"url\":\"classes/DropIndexBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DropIndexBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"DropIndexBuilder\"},{\"kind\":2048,\"name\":\"on\",\"url\":\"classes/DropIndexBuilder.html#on\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropIndexBuilder\"},{\"kind\":2048,\"name\":\"ifExists\",\"url\":\"classes/DropIndexBuilder.html#ifExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropIndexBuilder\"},{\"kind\":2048,\"name\":\"cascade\",\"url\":\"classes/DropIndexBuilder.html#cascade\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropIndexBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/DropIndexBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropIndexBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/DropIndexBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropIndexBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/DropIndexBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropIndexBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/DropIndexBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropIndexBuilder\"},{\"kind\":256,\"name\":\"DropIndexBuilderProps\",\"url\":\"interfaces/DropIndexBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/DropIndexBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropIndexBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/DropIndexBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropIndexBuilderProps\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/DropIndexBuilderProps.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropIndexBuilderProps\"},{\"kind\":128,\"name\":\"CreateSchemaBuilder\",\"url\":\"classes/CreateSchemaBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/CreateSchemaBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"CreateSchemaBuilder\"},{\"kind\":2048,\"name\":\"ifNotExists\",\"url\":\"classes/CreateSchemaBuilder.html#ifNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateSchemaBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/CreateSchemaBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateSchemaBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/CreateSchemaBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateSchemaBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/CreateSchemaBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateSchemaBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/CreateSchemaBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateSchemaBuilder\"},{\"kind\":256,\"name\":\"CreateSchemaBuilderProps\",\"url\":\"interfaces/CreateSchemaBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/CreateSchemaBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateSchemaBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/CreateSchemaBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateSchemaBuilderProps\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/CreateSchemaBuilderProps.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateSchemaBuilderProps\"},{\"kind\":128,\"name\":\"DropSchemaBuilder\",\"url\":\"classes/DropSchemaBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DropSchemaBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"DropSchemaBuilder\"},{\"kind\":2048,\"name\":\"ifExists\",\"url\":\"classes/DropSchemaBuilder.html#ifExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropSchemaBuilder\"},{\"kind\":2048,\"name\":\"cascade\",\"url\":\"classes/DropSchemaBuilder.html#cascade\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropSchemaBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/DropSchemaBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropSchemaBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/DropSchemaBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropSchemaBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/DropSchemaBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropSchemaBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/DropSchemaBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropSchemaBuilder\"},{\"kind\":256,\"name\":\"DropSchemaBuilderProps\",\"url\":\"interfaces/DropSchemaBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/DropSchemaBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropSchemaBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/DropSchemaBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropSchemaBuilderProps\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/DropSchemaBuilderProps.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropSchemaBuilderProps\"},{\"kind\":128,\"name\":\"ColumnDefinitionBuilder\",\"url\":\"classes/ColumnDefinitionBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/ColumnDefinitionBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"autoIncrement\",\"url\":\"classes/ColumnDefinitionBuilder.html#autoIncrement\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"primaryKey\",\"url\":\"classes/ColumnDefinitionBuilder.html#primaryKey\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"references\",\"url\":\"classes/ColumnDefinitionBuilder.html#references\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"onDelete\",\"url\":\"classes/ColumnDefinitionBuilder.html#onDelete\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"onUpdate\",\"url\":\"classes/ColumnDefinitionBuilder.html#onUpdate\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"unique\",\"url\":\"classes/ColumnDefinitionBuilder.html#unique\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"notNull\",\"url\":\"classes/ColumnDefinitionBuilder.html#notNull\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"unsigned\",\"url\":\"classes/ColumnDefinitionBuilder.html#unsigned\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"defaultTo\",\"url\":\"classes/ColumnDefinitionBuilder.html#defaultTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"check\",\"url\":\"classes/ColumnDefinitionBuilder.html#check\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"generatedAlwaysAs\",\"url\":\"classes/ColumnDefinitionBuilder.html#generatedAlwaysAs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"generatedAlwaysAsIdentity\",\"url\":\"classes/ColumnDefinitionBuilder.html#generatedAlwaysAsIdentity\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"generatedByDefaultAsIdentity\",\"url\":\"classes/ColumnDefinitionBuilder.html#generatedByDefaultAsIdentity\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"stored\",\"url\":\"classes/ColumnDefinitionBuilder.html#stored\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"modifyFront\",\"url\":\"classes/ColumnDefinitionBuilder.html#modifyFront\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"modifyEnd\",\"url\":\"classes/ColumnDefinitionBuilder.html#modifyEnd\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/ColumnDefinitionBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/ColumnDefinitionBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ColumnDefinitionBuilder\"},{\"kind\":4194304,\"name\":\"ColumnDefinitionBuilderCallback\",\"url\":\"types/ColumnDefinitionBuilderCallback.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/ColumnDefinitionBuilderCallback.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"ColumnDefinitionBuilderCallback\"},{\"kind\":256,\"name\":\"ForeignKeyConstraintBuilderInterface\",\"url\":\"interfaces/ForeignKeyConstraintBuilderInterface.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"onDelete\",\"url\":\"interfaces/ForeignKeyConstraintBuilderInterface.html#onDelete\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ForeignKeyConstraintBuilderInterface\"},{\"kind\":2048,\"name\":\"onUpdate\",\"url\":\"interfaces/ForeignKeyConstraintBuilderInterface.html#onUpdate\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ForeignKeyConstraintBuilderInterface\"},{\"kind\":128,\"name\":\"ForeignKeyConstraintBuilder\",\"url\":\"classes/ForeignKeyConstraintBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/ForeignKeyConstraintBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"ForeignKeyConstraintBuilder\"},{\"kind\":2048,\"name\":\"onDelete\",\"url\":\"classes/ForeignKeyConstraintBuilder.html#onDelete\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ForeignKeyConstraintBuilder\"},{\"kind\":2048,\"name\":\"onUpdate\",\"url\":\"classes/ForeignKeyConstraintBuilder.html#onUpdate\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ForeignKeyConstraintBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/ForeignKeyConstraintBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ForeignKeyConstraintBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/ForeignKeyConstraintBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"ForeignKeyConstraintBuilder\"},{\"kind\":128,\"name\":\"AlterTableBuilder\",\"url\":\"classes/AlterTableBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/AlterTableBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":2048,\"name\":\"renameTo\",\"url\":\"classes/AlterTableBuilder.html#renameTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":2048,\"name\":\"setSchema\",\"url\":\"classes/AlterTableBuilder.html#setSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":2048,\"name\":\"alterColumn\",\"url\":\"classes/AlterTableBuilder.html#alterColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":2048,\"name\":\"dropColumn\",\"url\":\"classes/AlterTableBuilder.html#dropColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":2048,\"name\":\"renameColumn\",\"url\":\"classes/AlterTableBuilder.html#renameColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":2048,\"name\":\"addColumn\",\"url\":\"classes/AlterTableBuilder.html#addColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":2048,\"name\":\"modifyColumn\",\"url\":\"classes/AlterTableBuilder.html#modifyColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":2048,\"name\":\"addUniqueConstraint\",\"url\":\"classes/AlterTableBuilder.html#addUniqueConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":2048,\"name\":\"addCheckConstraint\",\"url\":\"classes/AlterTableBuilder.html#addCheckConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":2048,\"name\":\"addForeignKeyConstraint\",\"url\":\"classes/AlterTableBuilder.html#addForeignKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":2048,\"name\":\"dropConstraint\",\"url\":\"classes/AlterTableBuilder.html#dropConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/AlterTableBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":2048,\"name\":\"call\",\"url\":\"classes/AlterTableBuilder.html#call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableBuilder\"},{\"kind\":256,\"name\":\"AlterTableBuilderProps\",\"url\":\"interfaces/AlterTableBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/AlterTableBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterTableBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/AlterTableBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterTableBuilderProps\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/AlterTableBuilderProps.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterTableBuilderProps\"},{\"kind\":256,\"name\":\"ColumnAlteringInterface\",\"url\":\"interfaces/ColumnAlteringInterface.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"alterColumn\",\"url\":\"interfaces/ColumnAlteringInterface.html#alterColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ColumnAlteringInterface\"},{\"kind\":2048,\"name\":\"dropColumn\",\"url\":\"interfaces/ColumnAlteringInterface.html#dropColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ColumnAlteringInterface\"},{\"kind\":2048,\"name\":\"renameColumn\",\"url\":\"interfaces/ColumnAlteringInterface.html#renameColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ColumnAlteringInterface\"},{\"kind\":2048,\"name\":\"addColumn\",\"url\":\"interfaces/ColumnAlteringInterface.html#addColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ColumnAlteringInterface\"},{\"kind\":2048,\"name\":\"modifyColumn\",\"url\":\"interfaces/ColumnAlteringInterface.html#modifyColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ColumnAlteringInterface\"},{\"kind\":128,\"name\":\"AlterTableColumnAlteringBuilder\",\"url\":\"classes/AlterTableColumnAlteringBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/AlterTableColumnAlteringBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"AlterTableColumnAlteringBuilder\"},{\"kind\":2048,\"name\":\"alterColumn\",\"url\":\"classes/AlterTableColumnAlteringBuilder.html#alterColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableColumnAlteringBuilder\"},{\"kind\":2048,\"name\":\"dropColumn\",\"url\":\"classes/AlterTableColumnAlteringBuilder.html#dropColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableColumnAlteringBuilder\"},{\"kind\":2048,\"name\":\"renameColumn\",\"url\":\"classes/AlterTableColumnAlteringBuilder.html#renameColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableColumnAlteringBuilder\"},{\"kind\":2048,\"name\":\"addColumn\",\"url\":\"classes/AlterTableColumnAlteringBuilder.html#addColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableColumnAlteringBuilder\"},{\"kind\":2048,\"name\":\"modifyColumn\",\"url\":\"classes/AlterTableColumnAlteringBuilder.html#modifyColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableColumnAlteringBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/AlterTableColumnAlteringBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableColumnAlteringBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/AlterTableColumnAlteringBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableColumnAlteringBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/AlterTableColumnAlteringBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterTableColumnAlteringBuilder\"},{\"kind\":256,\"name\":\"AlterTableColumnAlteringBuilderProps\",\"url\":\"interfaces/AlterTableColumnAlteringBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/AlterTableColumnAlteringBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface tsd-is-inherited\",\"parent\":\"AlterTableColumnAlteringBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/AlterTableColumnAlteringBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface tsd-is-inherited\",\"parent\":\"AlterTableColumnAlteringBuilderProps\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/AlterTableColumnAlteringBuilderProps.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface tsd-is-inherited\",\"parent\":\"AlterTableColumnAlteringBuilderProps\"},{\"kind\":128,\"name\":\"CreateViewBuilder\",\"url\":\"classes/CreateViewBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/CreateViewBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"CreateViewBuilder\"},{\"kind\":2048,\"name\":\"temporary\",\"url\":\"classes/CreateViewBuilder.html#temporary\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateViewBuilder\"},{\"kind\":2048,\"name\":\"materialized\",\"url\":\"classes/CreateViewBuilder.html#materialized\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateViewBuilder\"},{\"kind\":2048,\"name\":\"ifNotExists\",\"url\":\"classes/CreateViewBuilder.html#ifNotExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateViewBuilder\"},{\"kind\":2048,\"name\":\"orReplace\",\"url\":\"classes/CreateViewBuilder.html#orReplace\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateViewBuilder\"},{\"kind\":2048,\"name\":\"columns\",\"url\":\"classes/CreateViewBuilder.html#columns\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateViewBuilder\"},{\"kind\":2048,\"name\":\"as\",\"url\":\"classes/CreateViewBuilder.html#as\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateViewBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/CreateViewBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateViewBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/CreateViewBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateViewBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/CreateViewBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateViewBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/CreateViewBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CreateViewBuilder\"},{\"kind\":256,\"name\":\"CreateViewBuilderProps\",\"url\":\"interfaces/CreateViewBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/CreateViewBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateViewBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/CreateViewBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateViewBuilderProps\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/CreateViewBuilderProps.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateViewBuilderProps\"},{\"kind\":128,\"name\":\"DropViewBuilder\",\"url\":\"classes/DropViewBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DropViewBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"DropViewBuilder\"},{\"kind\":2048,\"name\":\"materialized\",\"url\":\"classes/DropViewBuilder.html#materialized\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropViewBuilder\"},{\"kind\":2048,\"name\":\"ifExists\",\"url\":\"classes/DropViewBuilder.html#ifExists\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropViewBuilder\"},{\"kind\":2048,\"name\":\"cascade\",\"url\":\"classes/DropViewBuilder.html#cascade\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropViewBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/DropViewBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropViewBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/DropViewBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropViewBuilder\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"classes/DropViewBuilder.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropViewBuilder\"},{\"kind\":2048,\"name\":\"execute\",\"url\":\"classes/DropViewBuilder.html#execute\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DropViewBuilder\"},{\"kind\":256,\"name\":\"DropViewBuilderProps\",\"url\":\"interfaces/DropViewBuilderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/DropViewBuilderProps.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropViewBuilderProps\"},{\"kind\":1024,\"name\":\"executor\",\"url\":\"interfaces/DropViewBuilderProps.html#executor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropViewBuilderProps\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/DropViewBuilderProps.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropViewBuilderProps\"},{\"kind\":128,\"name\":\"AlterColumnBuilder\",\"url\":\"classes/AlterColumnBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/AlterColumnBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"AlterColumnBuilder\"},{\"kind\":1024,\"name\":\"alterColumnNode\",\"url\":\"classes/AlterColumnBuilder.html#alterColumnNode\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"AlterColumnBuilder\"},{\"kind\":2048,\"name\":\"setDataType\",\"url\":\"classes/AlterColumnBuilder.html#setDataType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterColumnBuilder\"},{\"kind\":2048,\"name\":\"setDefault\",\"url\":\"classes/AlterColumnBuilder.html#setDefault\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterColumnBuilder\"},{\"kind\":2048,\"name\":\"dropDefault\",\"url\":\"classes/AlterColumnBuilder.html#dropDefault\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterColumnBuilder\"},{\"kind\":2048,\"name\":\"setNotNull\",\"url\":\"classes/AlterColumnBuilder.html#setNotNull\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterColumnBuilder\"},{\"kind\":2048,\"name\":\"dropNotNull\",\"url\":\"classes/AlterColumnBuilder.html#dropNotNull\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterColumnBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/AlterColumnBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlterColumnBuilder\"},{\"kind\":128,\"name\":\"AlteredColumnBuilder\",\"url\":\"classes/AlteredColumnBuilder.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/AlteredColumnBuilder.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"AlteredColumnBuilder\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"classes/AlteredColumnBuilder.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"AlteredColumnBuilder\"},{\"kind\":1024,\"name\":\"alterColumnNode\",\"url\":\"classes/AlteredColumnBuilder.html#alterColumnNode\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"AlteredColumnBuilder\"},{\"kind\":2048,\"name\":\"setDataType\",\"url\":\"classes/AlteredColumnBuilder.html#setDataType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"AlteredColumnBuilder\"},{\"kind\":2048,\"name\":\"setDefault\",\"url\":\"classes/AlteredColumnBuilder.html#setDefault\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"AlteredColumnBuilder\"},{\"kind\":2048,\"name\":\"dropDefault\",\"url\":\"classes/AlteredColumnBuilder.html#dropDefault\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"AlteredColumnBuilder\"},{\"kind\":2048,\"name\":\"setNotNull\",\"url\":\"classes/AlteredColumnBuilder.html#setNotNull\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"AlteredColumnBuilder\"},{\"kind\":2048,\"name\":\"dropNotNull\",\"url\":\"classes/AlteredColumnBuilder.html#dropNotNull\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"AlteredColumnBuilder\"},{\"kind\":2048,\"name\":\"$call\",\"url\":\"classes/AlteredColumnBuilder.html#_call\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"AlteredColumnBuilder\"},{\"kind\":4194304,\"name\":\"AlterColumnBuilderCallback\",\"url\":\"types/AlterColumnBuilderCallback.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/AlterColumnBuilderCallback.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"AlterColumnBuilderCallback\"},{\"kind\":128,\"name\":\"DynamicModule\",\"url\":\"classes/DynamicModule.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DynamicModule.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"DynamicModule\"},{\"kind\":2048,\"name\":\"ref\",\"url\":\"classes/DynamicModule.html#ref\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DynamicModule\"},{\"kind\":256,\"name\":\"Driver\",\"url\":\"interfaces/Driver.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"init\",\"url\":\"interfaces/Driver.html#init\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Driver\"},{\"kind\":2048,\"name\":\"acquireConnection\",\"url\":\"interfaces/Driver.html#acquireConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Driver\"},{\"kind\":2048,\"name\":\"beginTransaction\",\"url\":\"interfaces/Driver.html#beginTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Driver\"},{\"kind\":2048,\"name\":\"commitTransaction\",\"url\":\"interfaces/Driver.html#commitTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Driver\"},{\"kind\":2048,\"name\":\"rollbackTransaction\",\"url\":\"interfaces/Driver.html#rollbackTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Driver\"},{\"kind\":2048,\"name\":\"releaseConnection\",\"url\":\"interfaces/Driver.html#releaseConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Driver\"},{\"kind\":2048,\"name\":\"destroy\",\"url\":\"interfaces/Driver.html#destroy\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Driver\"},{\"kind\":256,\"name\":\"TransactionSettings\",\"url\":\"interfaces/TransactionSettings.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"isolationLevel\",\"url\":\"interfaces/TransactionSettings.html#isolationLevel\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"TransactionSettings\"},{\"kind\":32,\"name\":\"TRANSACTION_ISOLATION_LEVELS\",\"url\":\"variables/TRANSACTION_ISOLATION_LEVELS.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":4194304,\"name\":\"IsolationLevel\",\"url\":\"types/IsolationLevel.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"DatabaseConnection\",\"url\":\"interfaces/DatabaseConnection.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"executeQuery\",\"url\":\"interfaces/DatabaseConnection.html#executeQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"DatabaseConnection\"},{\"kind\":2048,\"name\":\"streamQuery\",\"url\":\"interfaces/DatabaseConnection.html#streamQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"DatabaseConnection\"},{\"kind\":256,\"name\":\"QueryResult\",\"url\":\"interfaces/QueryResult.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"numUpdatedOrDeletedRows\",\"url\":\"interfaces/QueryResult.html#numUpdatedOrDeletedRows\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"QueryResult\"},{\"kind\":1024,\"name\":\"numAffectedRows\",\"url\":\"interfaces/QueryResult.html#numAffectedRows\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"QueryResult\"},{\"kind\":1024,\"name\":\"insertId\",\"url\":\"interfaces/QueryResult.html#insertId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"QueryResult\"},{\"kind\":1024,\"name\":\"rows\",\"url\":\"interfaces/QueryResult.html#rows\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"QueryResult\"},{\"kind\":256,\"name\":\"ConnectionProvider\",\"url\":\"interfaces/ConnectionProvider.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"provideConnection\",\"url\":\"interfaces/ConnectionProvider.html#provideConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"ConnectionProvider\"},{\"kind\":128,\"name\":\"DefaultConnectionProvider\",\"url\":\"classes/DefaultConnectionProvider.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DefaultConnectionProvider.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"DefaultConnectionProvider\"},{\"kind\":2048,\"name\":\"provideConnection\",\"url\":\"classes/DefaultConnectionProvider.html#provideConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DefaultConnectionProvider\"},{\"kind\":128,\"name\":\"SingleConnectionProvider\",\"url\":\"classes/SingleConnectionProvider.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/SingleConnectionProvider.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"SingleConnectionProvider\"},{\"kind\":2048,\"name\":\"provideConnection\",\"url\":\"classes/SingleConnectionProvider.html#provideConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SingleConnectionProvider\"},{\"kind\":128,\"name\":\"DummyDriver\",\"url\":\"classes/DummyDriver.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DummyDriver.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"DummyDriver\"},{\"kind\":2048,\"name\":\"init\",\"url\":\"classes/DummyDriver.html#init\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DummyDriver\"},{\"kind\":2048,\"name\":\"acquireConnection\",\"url\":\"classes/DummyDriver.html#acquireConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DummyDriver\"},{\"kind\":2048,\"name\":\"beginTransaction\",\"url\":\"classes/DummyDriver.html#beginTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DummyDriver\"},{\"kind\":2048,\"name\":\"commitTransaction\",\"url\":\"classes/DummyDriver.html#commitTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DummyDriver\"},{\"kind\":2048,\"name\":\"rollbackTransaction\",\"url\":\"classes/DummyDriver.html#rollbackTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DummyDriver\"},{\"kind\":2048,\"name\":\"releaseConnection\",\"url\":\"classes/DummyDriver.html#releaseConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DummyDriver\"},{\"kind\":2048,\"name\":\"destroy\",\"url\":\"classes/DummyDriver.html#destroy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DummyDriver\"},{\"kind\":256,\"name\":\"Dialect\",\"url\":\"interfaces/Dialect.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"createDriver\",\"url\":\"interfaces/Dialect.html#createDriver\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Dialect\"},{\"kind\":2048,\"name\":\"createQueryCompiler\",\"url\":\"interfaces/Dialect.html#createQueryCompiler\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Dialect\"},{\"kind\":2048,\"name\":\"createAdapter\",\"url\":\"interfaces/Dialect.html#createAdapter\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Dialect\"},{\"kind\":2048,\"name\":\"createIntrospector\",\"url\":\"interfaces/Dialect.html#createIntrospector\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Dialect\"},{\"kind\":256,\"name\":\"DialectAdapter\",\"url\":\"interfaces/DialectAdapter.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"supportsTransactionalDdl\",\"url\":\"interfaces/DialectAdapter.html#supportsTransactionalDdl\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DialectAdapter\"},{\"kind\":1024,\"name\":\"supportsReturning\",\"url\":\"interfaces/DialectAdapter.html#supportsReturning\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DialectAdapter\"},{\"kind\":2048,\"name\":\"acquireMigrationLock\",\"url\":\"interfaces/DialectAdapter.html#acquireMigrationLock\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"DialectAdapter\"},{\"kind\":2048,\"name\":\"releaseMigrationLock\",\"url\":\"interfaces/DialectAdapter.html#releaseMigrationLock\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"DialectAdapter\"},{\"kind\":256,\"name\":\"MigrationLockOptions\",\"url\":\"interfaces/MigrationLockOptions.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"lockTable\",\"url\":\"interfaces/MigrationLockOptions.html#lockTable\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigrationLockOptions\"},{\"kind\":1024,\"name\":\"lockRowId\",\"url\":\"interfaces/MigrationLockOptions.html#lockRowId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigrationLockOptions\"},{\"kind\":1024,\"name\":\"lockTableSchema\",\"url\":\"interfaces/MigrationLockOptions.html#lockTableSchema\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigrationLockOptions\"},{\"kind\":128,\"name\":\"DialectAdapterBase\",\"url\":\"classes/DialectAdapterBase.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DialectAdapterBase.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"DialectAdapterBase\"},{\"kind\":262144,\"name\":\"supportsTransactionalDdl\",\"url\":\"classes/DialectAdapterBase.html#supportsTransactionalDdl\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"DialectAdapterBase\"},{\"kind\":262144,\"name\":\"supportsReturning\",\"url\":\"classes/DialectAdapterBase.html#supportsReturning\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"DialectAdapterBase\"},{\"kind\":2048,\"name\":\"acquireMigrationLock\",\"url\":\"classes/DialectAdapterBase.html#acquireMigrationLock\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DialectAdapterBase\"},{\"kind\":2048,\"name\":\"releaseMigrationLock\",\"url\":\"classes/DialectAdapterBase.html#releaseMigrationLock\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DialectAdapterBase\"},{\"kind\":256,\"name\":\"DatabaseIntrospector\",\"url\":\"interfaces/DatabaseIntrospector.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"getSchemas\",\"url\":\"interfaces/DatabaseIntrospector.html#getSchemas\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"DatabaseIntrospector\"},{\"kind\":2048,\"name\":\"getTables\",\"url\":\"interfaces/DatabaseIntrospector.html#getTables\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"DatabaseIntrospector\"},{\"kind\":2048,\"name\":\"getMetadata\",\"url\":\"interfaces/DatabaseIntrospector.html#getMetadata\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"DatabaseIntrospector\"},{\"kind\":256,\"name\":\"DatabaseMetadataOptions\",\"url\":\"interfaces/DatabaseMetadataOptions.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"withInternalKyselyTables\",\"url\":\"interfaces/DatabaseMetadataOptions.html#withInternalKyselyTables\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DatabaseMetadataOptions\"},{\"kind\":256,\"name\":\"SchemaMetadata\",\"url\":\"interfaces/SchemaMetadata.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/SchemaMetadata.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SchemaMetadata\"},{\"kind\":256,\"name\":\"DatabaseMetadata\",\"url\":\"interfaces/DatabaseMetadata.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"tables\",\"url\":\"interfaces/DatabaseMetadata.html#tables\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DatabaseMetadata\"},{\"kind\":256,\"name\":\"TableMetadata\",\"url\":\"interfaces/TableMetadata.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/TableMetadata.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"TableMetadata\"},{\"kind\":1024,\"name\":\"isView\",\"url\":\"interfaces/TableMetadata.html#isView\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"TableMetadata\"},{\"kind\":1024,\"name\":\"columns\",\"url\":\"interfaces/TableMetadata.html#columns\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"TableMetadata\"},{\"kind\":1024,\"name\":\"schema\",\"url\":\"interfaces/TableMetadata.html#schema\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"TableMetadata\"},{\"kind\":256,\"name\":\"ColumnMetadata\",\"url\":\"interfaces/ColumnMetadata.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/ColumnMetadata.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnMetadata\"},{\"kind\":1024,\"name\":\"dataType\",\"url\":\"interfaces/ColumnMetadata.html#dataType\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnMetadata\"},{\"kind\":1024,\"name\":\"dataTypeSchema\",\"url\":\"interfaces/ColumnMetadata.html#dataTypeSchema\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnMetadata\"},{\"kind\":1024,\"name\":\"isAutoIncrementing\",\"url\":\"interfaces/ColumnMetadata.html#isAutoIncrementing\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnMetadata\"},{\"kind\":1024,\"name\":\"isNullable\",\"url\":\"interfaces/ColumnMetadata.html#isNullable\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnMetadata\"},{\"kind\":1024,\"name\":\"hasDefaultValue\",\"url\":\"interfaces/ColumnMetadata.html#hasDefaultValue\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnMetadata\"},{\"kind\":128,\"name\":\"SqliteDialect\",\"url\":\"classes/SqliteDialect.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/SqliteDialect.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"SqliteDialect\"},{\"kind\":2048,\"name\":\"createDriver\",\"url\":\"classes/SqliteDialect.html#createDriver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteDialect\"},{\"kind\":2048,\"name\":\"createQueryCompiler\",\"url\":\"classes/SqliteDialect.html#createQueryCompiler\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteDialect\"},{\"kind\":2048,\"name\":\"createAdapter\",\"url\":\"classes/SqliteDialect.html#createAdapter\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteDialect\"},{\"kind\":2048,\"name\":\"createIntrospector\",\"url\":\"classes/SqliteDialect.html#createIntrospector\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteDialect\"},{\"kind\":256,\"name\":\"SqliteDialectConfig\",\"url\":\"interfaces/SqliteDialectConfig.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"database\",\"url\":\"interfaces/SqliteDialectConfig.html#database\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SqliteDialectConfig\"},{\"kind\":1024,\"name\":\"onCreateConnection\",\"url\":\"interfaces/SqliteDialectConfig.html#onCreateConnection\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SqliteDialectConfig\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/SqliteDialectConfig.html#onCreateConnection.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-property\",\"parent\":\"SqliteDialectConfig.onCreateConnection\"},{\"kind\":256,\"name\":\"SqliteDatabase\",\"url\":\"interfaces/SqliteDatabase.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"close\",\"url\":\"interfaces/SqliteDatabase.html#close\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"SqliteDatabase\"},{\"kind\":2048,\"name\":\"prepare\",\"url\":\"interfaces/SqliteDatabase.html#prepare\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"SqliteDatabase\"},{\"kind\":256,\"name\":\"SqliteStatement\",\"url\":\"interfaces/SqliteStatement.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"reader\",\"url\":\"interfaces/SqliteStatement.html#reader\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SqliteStatement\"},{\"kind\":2048,\"name\":\"all\",\"url\":\"interfaces/SqliteStatement.html#all\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"SqliteStatement\"},{\"kind\":2048,\"name\":\"run\",\"url\":\"interfaces/SqliteStatement.html#run\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"SqliteStatement\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/SqliteStatement.html#run.run-1.__type\",\"classes\":\"tsd-kind-type-literal\",\"parent\":\"SqliteStatement.run.run\"},{\"kind\":1024,\"name\":\"changes\",\"url\":\"interfaces/SqliteStatement.html#run.run-1.__type.changes\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SqliteStatement.run.run.__type\"},{\"kind\":1024,\"name\":\"lastInsertRowid\",\"url\":\"interfaces/SqliteStatement.html#run.run-1.__type.lastInsertRowid\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"SqliteStatement.run.run.__type\"},{\"kind\":128,\"name\":\"SqliteDriver\",\"url\":\"classes/SqliteDriver.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/SqliteDriver.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"SqliteDriver\"},{\"kind\":2048,\"name\":\"init\",\"url\":\"classes/SqliteDriver.html#init\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteDriver\"},{\"kind\":2048,\"name\":\"acquireConnection\",\"url\":\"classes/SqliteDriver.html#acquireConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteDriver\"},{\"kind\":2048,\"name\":\"beginTransaction\",\"url\":\"classes/SqliteDriver.html#beginTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteDriver\"},{\"kind\":2048,\"name\":\"commitTransaction\",\"url\":\"classes/SqliteDriver.html#commitTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteDriver\"},{\"kind\":2048,\"name\":\"rollbackTransaction\",\"url\":\"classes/SqliteDriver.html#rollbackTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteDriver\"},{\"kind\":2048,\"name\":\"releaseConnection\",\"url\":\"classes/SqliteDriver.html#releaseConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteDriver\"},{\"kind\":2048,\"name\":\"destroy\",\"url\":\"classes/SqliteDriver.html#destroy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteDriver\"},{\"kind\":128,\"name\":\"PostgresQueryCompiler\",\"url\":\"classes/PostgresQueryCompiler.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/PostgresQueryCompiler.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"sanitizeIdentifier\",\"url\":\"classes/PostgresQueryCompiler.html#sanitizeIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":262144,\"name\":\"numParameters\",\"url\":\"classes/PostgresQueryCompiler.html#numParameters\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"compileQuery\",\"url\":\"classes/PostgresQueryCompiler.html#compileQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"getSql\",\"url\":\"classes/PostgresQueryCompiler.html#getSql\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelectQuery\",\"url\":\"classes/PostgresQueryCompiler.html#visitSelectQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitFrom\",\"url\":\"classes/PostgresQueryCompiler.html#visitFrom\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelection\",\"url\":\"classes/PostgresQueryCompiler.html#visitSelection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitColumn\",\"url\":\"classes/PostgresQueryCompiler.html#visitColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"compileDistinctOn\",\"url\":\"classes/PostgresQueryCompiler.html#compileDistinctOn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"compileList\",\"url\":\"classes/PostgresQueryCompiler.html#compileList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitWhere\",\"url\":\"classes/PostgresQueryCompiler.html#visitWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitHaving\",\"url\":\"classes/PostgresQueryCompiler.html#visitHaving\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitInsertQuery\",\"url\":\"classes/PostgresQueryCompiler.html#visitInsertQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitValues\",\"url\":\"classes/PostgresQueryCompiler.html#visitValues\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDeleteQuery\",\"url\":\"classes/PostgresQueryCompiler.html#visitDeleteQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitReturning\",\"url\":\"classes/PostgresQueryCompiler.html#visitReturning\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAlias\",\"url\":\"classes/PostgresQueryCompiler.html#visitAlias\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitReference\",\"url\":\"classes/PostgresQueryCompiler.html#visitReference\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelectAll\",\"url\":\"classes/PostgresQueryCompiler.html#visitSelectAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitIdentifier\",\"url\":\"classes/PostgresQueryCompiler.html#visitIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"compileUnwrappedIdentifier\",\"url\":\"classes/PostgresQueryCompiler.html#compileUnwrappedIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAnd\",\"url\":\"classes/PostgresQueryCompiler.html#visitAnd\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOr\",\"url\":\"classes/PostgresQueryCompiler.html#visitOr\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitValue\",\"url\":\"classes/PostgresQueryCompiler.html#visitValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitValueList\",\"url\":\"classes/PostgresQueryCompiler.html#visitValueList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPrimitiveValueList\",\"url\":\"classes/PostgresQueryCompiler.html#visitPrimitiveValueList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitParens\",\"url\":\"classes/PostgresQueryCompiler.html#visitParens\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitJoin\",\"url\":\"classes/PostgresQueryCompiler.html#visitJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOn\",\"url\":\"classes/PostgresQueryCompiler.html#visitOn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitRaw\",\"url\":\"classes/PostgresQueryCompiler.html#visitRaw\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOperator\",\"url\":\"classes/PostgresQueryCompiler.html#visitOperator\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitTable\",\"url\":\"classes/PostgresQueryCompiler.html#visitTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSchemableIdentifier\",\"url\":\"classes/PostgresQueryCompiler.html#visitSchemableIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateTable\",\"url\":\"classes/PostgresQueryCompiler.html#visitCreateTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitColumnDefinition\",\"url\":\"classes/PostgresQueryCompiler.html#visitColumnDefinition\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"getAutoIncrement\",\"url\":\"classes/PostgresQueryCompiler.html#getAutoIncrement\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitReferences\",\"url\":\"classes/PostgresQueryCompiler.html#visitReferences\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropTable\",\"url\":\"classes/PostgresQueryCompiler.html#visitDropTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDataType\",\"url\":\"classes/PostgresQueryCompiler.html#visitDataType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOrderBy\",\"url\":\"classes/PostgresQueryCompiler.html#visitOrderBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOrderByItem\",\"url\":\"classes/PostgresQueryCompiler.html#visitOrderByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitGroupBy\",\"url\":\"classes/PostgresQueryCompiler.html#visitGroupBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitGroupByItem\",\"url\":\"classes/PostgresQueryCompiler.html#visitGroupByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUpdateQuery\",\"url\":\"classes/PostgresQueryCompiler.html#visitUpdateQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitColumnUpdate\",\"url\":\"classes/PostgresQueryCompiler.html#visitColumnUpdate\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitLimit\",\"url\":\"classes/PostgresQueryCompiler.html#visitLimit\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOffset\",\"url\":\"classes/PostgresQueryCompiler.html#visitOffset\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOnConflict\",\"url\":\"classes/PostgresQueryCompiler.html#visitOnConflict\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOnDuplicateKey\",\"url\":\"classes/PostgresQueryCompiler.html#visitOnDuplicateKey\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateIndex\",\"url\":\"classes/PostgresQueryCompiler.html#visitCreateIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropIndex\",\"url\":\"classes/PostgresQueryCompiler.html#visitDropIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateSchema\",\"url\":\"classes/PostgresQueryCompiler.html#visitCreateSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropSchema\",\"url\":\"classes/PostgresQueryCompiler.html#visitDropSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPrimaryKeyConstraint\",\"url\":\"classes/PostgresQueryCompiler.html#visitPrimaryKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUniqueConstraint\",\"url\":\"classes/PostgresQueryCompiler.html#visitUniqueConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCheckConstraint\",\"url\":\"classes/PostgresQueryCompiler.html#visitCheckConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitForeignKeyConstraint\",\"url\":\"classes/PostgresQueryCompiler.html#visitForeignKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitList\",\"url\":\"classes/PostgresQueryCompiler.html#visitList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitWith\",\"url\":\"classes/PostgresQueryCompiler.html#visitWith\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCommonTableExpression\",\"url\":\"classes/PostgresQueryCompiler.html#visitCommonTableExpression\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCommonTableExpressionName\",\"url\":\"classes/PostgresQueryCompiler.html#visitCommonTableExpressionName\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAlterTable\",\"url\":\"classes/PostgresQueryCompiler.html#visitAlterTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAddColumn\",\"url\":\"classes/PostgresQueryCompiler.html#visitAddColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitRenameColumn\",\"url\":\"classes/PostgresQueryCompiler.html#visitRenameColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropColumn\",\"url\":\"classes/PostgresQueryCompiler.html#visitDropColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAlterColumn\",\"url\":\"classes/PostgresQueryCompiler.html#visitAlterColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitModifyColumn\",\"url\":\"classes/PostgresQueryCompiler.html#visitModifyColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAddConstraint\",\"url\":\"classes/PostgresQueryCompiler.html#visitAddConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropConstraint\",\"url\":\"classes/PostgresQueryCompiler.html#visitDropConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSetOperation\",\"url\":\"classes/PostgresQueryCompiler.html#visitSetOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateView\",\"url\":\"classes/PostgresQueryCompiler.html#visitCreateView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropView\",\"url\":\"classes/PostgresQueryCompiler.html#visitDropView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitGenerated\",\"url\":\"classes/PostgresQueryCompiler.html#visitGenerated\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDefaultValue\",\"url\":\"classes/PostgresQueryCompiler.html#visitDefaultValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelectModifier\",\"url\":\"classes/PostgresQueryCompiler.html#visitSelectModifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateType\",\"url\":\"classes/PostgresQueryCompiler.html#visitCreateType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropType\",\"url\":\"classes/PostgresQueryCompiler.html#visitDropType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitExplain\",\"url\":\"classes/PostgresQueryCompiler.html#visitExplain\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDefaultInsertValue\",\"url\":\"classes/PostgresQueryCompiler.html#visitDefaultInsertValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAggregateFunction\",\"url\":\"classes/PostgresQueryCompiler.html#visitAggregateFunction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOver\",\"url\":\"classes/PostgresQueryCompiler.html#visitOver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPartitionBy\",\"url\":\"classes/PostgresQueryCompiler.html#visitPartitionBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPartitionByItem\",\"url\":\"classes/PostgresQueryCompiler.html#visitPartitionByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitBinaryOperation\",\"url\":\"classes/PostgresQueryCompiler.html#visitBinaryOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUnaryOperation\",\"url\":\"classes/PostgresQueryCompiler.html#visitUnaryOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"isMinusOperator\",\"url\":\"classes/PostgresQueryCompiler.html#isMinusOperator\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUsing\",\"url\":\"classes/PostgresQueryCompiler.html#visitUsing\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitFunction\",\"url\":\"classes/PostgresQueryCompiler.html#visitFunction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCase\",\"url\":\"classes/PostgresQueryCompiler.html#visitCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitWhen\",\"url\":\"classes/PostgresQueryCompiler.html#visitWhen\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"append\",\"url\":\"classes/PostgresQueryCompiler.html#append\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"appendValue\",\"url\":\"classes/PostgresQueryCompiler.html#appendValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"getLeftIdentifierWrapper\",\"url\":\"classes/PostgresQueryCompiler.html#getLeftIdentifierWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"getRightIdentifierWrapper\",\"url\":\"classes/PostgresQueryCompiler.html#getRightIdentifierWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"getCurrentParameterPlaceholder\",\"url\":\"classes/PostgresQueryCompiler.html#getCurrentParameterPlaceholder\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"getLeftExplainOptionsWrapper\",\"url\":\"classes/PostgresQueryCompiler.html#getLeftExplainOptionsWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"getExplainOptionAssignment\",\"url\":\"classes/PostgresQueryCompiler.html#getExplainOptionAssignment\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"getExplainOptionsDelimiter\",\"url\":\"classes/PostgresQueryCompiler.html#getExplainOptionsDelimiter\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"getRightExplainOptionsWrapper\",\"url\":\"classes/PostgresQueryCompiler.html#getRightExplainOptionsWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"addParameter\",\"url\":\"classes/PostgresQueryCompiler.html#addParameter\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"appendImmediateValue\",\"url\":\"classes/PostgresQueryCompiler.html#appendImmediateValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":1024,\"name\":\"nodeStack\",\"url\":\"classes/PostgresQueryCompiler.html#nodeStack\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":262144,\"name\":\"parentNode\",\"url\":\"classes/PostgresQueryCompiler.html#parentNode\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":2048,\"name\":\"visitNode\",\"url\":\"classes/PostgresQueryCompiler.html#visitNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"PostgresQueryCompiler\"},{\"kind\":128,\"name\":\"PostgresIntrospector\",\"url\":\"classes/PostgresIntrospector.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/PostgresIntrospector.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"PostgresIntrospector\"},{\"kind\":2048,\"name\":\"getSchemas\",\"url\":\"classes/PostgresIntrospector.html#getSchemas\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresIntrospector\"},{\"kind\":2048,\"name\":\"getTables\",\"url\":\"classes/PostgresIntrospector.html#getTables\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresIntrospector\"},{\"kind\":2048,\"name\":\"getMetadata\",\"url\":\"classes/PostgresIntrospector.html#getMetadata\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresIntrospector\"},{\"kind\":128,\"name\":\"PostgresAdapter\",\"url\":\"classes/PostgresAdapter.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/PostgresAdapter.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"PostgresAdapter\"},{\"kind\":262144,\"name\":\"supportsTransactionalDdl\",\"url\":\"classes/PostgresAdapter.html#supportsTransactionalDdl\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"PostgresAdapter\"},{\"kind\":262144,\"name\":\"supportsReturning\",\"url\":\"classes/PostgresAdapter.html#supportsReturning\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"PostgresAdapter\"},{\"kind\":2048,\"name\":\"acquireMigrationLock\",\"url\":\"classes/PostgresAdapter.html#acquireMigrationLock\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresAdapter\"},{\"kind\":2048,\"name\":\"releaseMigrationLock\",\"url\":\"classes/PostgresAdapter.html#releaseMigrationLock\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresAdapter\"},{\"kind\":128,\"name\":\"MysqlDialect\",\"url\":\"classes/MysqlDialect.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/MysqlDialect.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"MysqlDialect\"},{\"kind\":2048,\"name\":\"createDriver\",\"url\":\"classes/MysqlDialect.html#createDriver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlDialect\"},{\"kind\":2048,\"name\":\"createQueryCompiler\",\"url\":\"classes/MysqlDialect.html#createQueryCompiler\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlDialect\"},{\"kind\":2048,\"name\":\"createAdapter\",\"url\":\"classes/MysqlDialect.html#createAdapter\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlDialect\"},{\"kind\":2048,\"name\":\"createIntrospector\",\"url\":\"classes/MysqlDialect.html#createIntrospector\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlDialect\"},{\"kind\":256,\"name\":\"MysqlDialectConfig\",\"url\":\"interfaces/MysqlDialectConfig.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"pool\",\"url\":\"interfaces/MysqlDialectConfig.html#pool\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MysqlDialectConfig\"},{\"kind\":1024,\"name\":\"onCreateConnection\",\"url\":\"interfaces/MysqlDialectConfig.html#onCreateConnection\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MysqlDialectConfig\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/MysqlDialectConfig.html#onCreateConnection.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-property\",\"parent\":\"MysqlDialectConfig.onCreateConnection\"},{\"kind\":256,\"name\":\"MysqlPool\",\"url\":\"interfaces/MysqlPool.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"getConnection\",\"url\":\"interfaces/MysqlPool.html#getConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"MysqlPool\"},{\"kind\":2048,\"name\":\"end\",\"url\":\"interfaces/MysqlPool.html#end\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"MysqlPool\"},{\"kind\":256,\"name\":\"MysqlPoolConnection\",\"url\":\"interfaces/MysqlPoolConnection.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"query\",\"url\":\"interfaces/MysqlPoolConnection.html#query\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"MysqlPoolConnection\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/MysqlPoolConnection.html#query.query-1.__type\",\"classes\":\"tsd-kind-type-literal\",\"parent\":\"MysqlPoolConnection.query.query\"},{\"kind\":1024,\"name\":\"stream\",\"url\":\"interfaces/MysqlPoolConnection.html#query.query-1.__type.stream\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"MysqlPoolConnection.query.query.__type\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/MysqlPoolConnection.html#query.query-1.__type.stream.__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-property\",\"parent\":\"MysqlPoolConnection.query.query.__type.stream\"},{\"kind\":2048,\"name\":\"release\",\"url\":\"interfaces/MysqlPoolConnection.html#release\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"MysqlPoolConnection\"},{\"kind\":256,\"name\":\"MysqlStreamOptions\",\"url\":\"interfaces/MysqlStreamOptions.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"highWaterMark\",\"url\":\"interfaces/MysqlStreamOptions.html#highWaterMark\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MysqlStreamOptions\"},{\"kind\":1024,\"name\":\"objectMode\",\"url\":\"interfaces/MysqlStreamOptions.html#objectMode\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MysqlStreamOptions\"},{\"kind\":256,\"name\":\"MysqlStream\",\"url\":\"interfaces/MysqlStream.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"[asyncIterator]\",\"url\":\"interfaces/MysqlStream.html#_asyncIterator_\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"MysqlStream\"},{\"kind\":256,\"name\":\"MysqlOkPacket\",\"url\":\"interfaces/MysqlOkPacket.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"affectedRows\",\"url\":\"interfaces/MysqlOkPacket.html#affectedRows\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MysqlOkPacket\"},{\"kind\":1024,\"name\":\"insertId\",\"url\":\"interfaces/MysqlOkPacket.html#insertId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MysqlOkPacket\"},{\"kind\":4194304,\"name\":\"MysqlQueryResult\",\"url\":\"types/MysqlQueryResult.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":128,\"name\":\"MysqlDriver\",\"url\":\"classes/MysqlDriver.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/MysqlDriver.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"MysqlDriver\"},{\"kind\":2048,\"name\":\"init\",\"url\":\"classes/MysqlDriver.html#init\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlDriver\"},{\"kind\":2048,\"name\":\"acquireConnection\",\"url\":\"classes/MysqlDriver.html#acquireConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlDriver\"},{\"kind\":2048,\"name\":\"beginTransaction\",\"url\":\"classes/MysqlDriver.html#beginTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlDriver\"},{\"kind\":2048,\"name\":\"commitTransaction\",\"url\":\"classes/MysqlDriver.html#commitTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlDriver\"},{\"kind\":2048,\"name\":\"rollbackTransaction\",\"url\":\"classes/MysqlDriver.html#rollbackTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlDriver\"},{\"kind\":2048,\"name\":\"releaseConnection\",\"url\":\"classes/MysqlDriver.html#releaseConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlDriver\"},{\"kind\":2048,\"name\":\"destroy\",\"url\":\"classes/MysqlDriver.html#destroy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlDriver\"},{\"kind\":128,\"name\":\"MysqlQueryCompiler\",\"url\":\"classes/MysqlQueryCompiler.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/MysqlQueryCompiler.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"getCurrentParameterPlaceholder\",\"url\":\"classes/MysqlQueryCompiler.html#getCurrentParameterPlaceholder\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"getLeftExplainOptionsWrapper\",\"url\":\"classes/MysqlQueryCompiler.html#getLeftExplainOptionsWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"getExplainOptionAssignment\",\"url\":\"classes/MysqlQueryCompiler.html#getExplainOptionAssignment\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"getExplainOptionsDelimiter\",\"url\":\"classes/MysqlQueryCompiler.html#getExplainOptionsDelimiter\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"getRightExplainOptionsWrapper\",\"url\":\"classes/MysqlQueryCompiler.html#getRightExplainOptionsWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"getLeftIdentifierWrapper\",\"url\":\"classes/MysqlQueryCompiler.html#getLeftIdentifierWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"getRightIdentifierWrapper\",\"url\":\"classes/MysqlQueryCompiler.html#getRightIdentifierWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"sanitizeIdentifier\",\"url\":\"classes/MysqlQueryCompiler.html#sanitizeIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":262144,\"name\":\"numParameters\",\"url\":\"classes/MysqlQueryCompiler.html#numParameters\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"compileQuery\",\"url\":\"classes/MysqlQueryCompiler.html#compileQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"getSql\",\"url\":\"classes/MysqlQueryCompiler.html#getSql\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelectQuery\",\"url\":\"classes/MysqlQueryCompiler.html#visitSelectQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitFrom\",\"url\":\"classes/MysqlQueryCompiler.html#visitFrom\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelection\",\"url\":\"classes/MysqlQueryCompiler.html#visitSelection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitColumn\",\"url\":\"classes/MysqlQueryCompiler.html#visitColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"compileDistinctOn\",\"url\":\"classes/MysqlQueryCompiler.html#compileDistinctOn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"compileList\",\"url\":\"classes/MysqlQueryCompiler.html#compileList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitWhere\",\"url\":\"classes/MysqlQueryCompiler.html#visitWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitHaving\",\"url\":\"classes/MysqlQueryCompiler.html#visitHaving\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitInsertQuery\",\"url\":\"classes/MysqlQueryCompiler.html#visitInsertQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitValues\",\"url\":\"classes/MysqlQueryCompiler.html#visitValues\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDeleteQuery\",\"url\":\"classes/MysqlQueryCompiler.html#visitDeleteQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitReturning\",\"url\":\"classes/MysqlQueryCompiler.html#visitReturning\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAlias\",\"url\":\"classes/MysqlQueryCompiler.html#visitAlias\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitReference\",\"url\":\"classes/MysqlQueryCompiler.html#visitReference\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelectAll\",\"url\":\"classes/MysqlQueryCompiler.html#visitSelectAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitIdentifier\",\"url\":\"classes/MysqlQueryCompiler.html#visitIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"compileUnwrappedIdentifier\",\"url\":\"classes/MysqlQueryCompiler.html#compileUnwrappedIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAnd\",\"url\":\"classes/MysqlQueryCompiler.html#visitAnd\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOr\",\"url\":\"classes/MysqlQueryCompiler.html#visitOr\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitValue\",\"url\":\"classes/MysqlQueryCompiler.html#visitValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitValueList\",\"url\":\"classes/MysqlQueryCompiler.html#visitValueList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPrimitiveValueList\",\"url\":\"classes/MysqlQueryCompiler.html#visitPrimitiveValueList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitParens\",\"url\":\"classes/MysqlQueryCompiler.html#visitParens\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitJoin\",\"url\":\"classes/MysqlQueryCompiler.html#visitJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOn\",\"url\":\"classes/MysqlQueryCompiler.html#visitOn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitRaw\",\"url\":\"classes/MysqlQueryCompiler.html#visitRaw\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOperator\",\"url\":\"classes/MysqlQueryCompiler.html#visitOperator\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitTable\",\"url\":\"classes/MysqlQueryCompiler.html#visitTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSchemableIdentifier\",\"url\":\"classes/MysqlQueryCompiler.html#visitSchemableIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateTable\",\"url\":\"classes/MysqlQueryCompiler.html#visitCreateTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitColumnDefinition\",\"url\":\"classes/MysqlQueryCompiler.html#visitColumnDefinition\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"getAutoIncrement\",\"url\":\"classes/MysqlQueryCompiler.html#getAutoIncrement\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitReferences\",\"url\":\"classes/MysqlQueryCompiler.html#visitReferences\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropTable\",\"url\":\"classes/MysqlQueryCompiler.html#visitDropTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDataType\",\"url\":\"classes/MysqlQueryCompiler.html#visitDataType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOrderBy\",\"url\":\"classes/MysqlQueryCompiler.html#visitOrderBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOrderByItem\",\"url\":\"classes/MysqlQueryCompiler.html#visitOrderByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitGroupBy\",\"url\":\"classes/MysqlQueryCompiler.html#visitGroupBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitGroupByItem\",\"url\":\"classes/MysqlQueryCompiler.html#visitGroupByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUpdateQuery\",\"url\":\"classes/MysqlQueryCompiler.html#visitUpdateQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitColumnUpdate\",\"url\":\"classes/MysqlQueryCompiler.html#visitColumnUpdate\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitLimit\",\"url\":\"classes/MysqlQueryCompiler.html#visitLimit\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOffset\",\"url\":\"classes/MysqlQueryCompiler.html#visitOffset\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOnConflict\",\"url\":\"classes/MysqlQueryCompiler.html#visitOnConflict\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOnDuplicateKey\",\"url\":\"classes/MysqlQueryCompiler.html#visitOnDuplicateKey\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateIndex\",\"url\":\"classes/MysqlQueryCompiler.html#visitCreateIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropIndex\",\"url\":\"classes/MysqlQueryCompiler.html#visitDropIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateSchema\",\"url\":\"classes/MysqlQueryCompiler.html#visitCreateSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropSchema\",\"url\":\"classes/MysqlQueryCompiler.html#visitDropSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPrimaryKeyConstraint\",\"url\":\"classes/MysqlQueryCompiler.html#visitPrimaryKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUniqueConstraint\",\"url\":\"classes/MysqlQueryCompiler.html#visitUniqueConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCheckConstraint\",\"url\":\"classes/MysqlQueryCompiler.html#visitCheckConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitForeignKeyConstraint\",\"url\":\"classes/MysqlQueryCompiler.html#visitForeignKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitList\",\"url\":\"classes/MysqlQueryCompiler.html#visitList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitWith\",\"url\":\"classes/MysqlQueryCompiler.html#visitWith\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCommonTableExpression\",\"url\":\"classes/MysqlQueryCompiler.html#visitCommonTableExpression\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCommonTableExpressionName\",\"url\":\"classes/MysqlQueryCompiler.html#visitCommonTableExpressionName\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAlterTable\",\"url\":\"classes/MysqlQueryCompiler.html#visitAlterTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAddColumn\",\"url\":\"classes/MysqlQueryCompiler.html#visitAddColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitRenameColumn\",\"url\":\"classes/MysqlQueryCompiler.html#visitRenameColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropColumn\",\"url\":\"classes/MysqlQueryCompiler.html#visitDropColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAlterColumn\",\"url\":\"classes/MysqlQueryCompiler.html#visitAlterColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitModifyColumn\",\"url\":\"classes/MysqlQueryCompiler.html#visitModifyColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAddConstraint\",\"url\":\"classes/MysqlQueryCompiler.html#visitAddConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropConstraint\",\"url\":\"classes/MysqlQueryCompiler.html#visitDropConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSetOperation\",\"url\":\"classes/MysqlQueryCompiler.html#visitSetOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateView\",\"url\":\"classes/MysqlQueryCompiler.html#visitCreateView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropView\",\"url\":\"classes/MysqlQueryCompiler.html#visitDropView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitGenerated\",\"url\":\"classes/MysqlQueryCompiler.html#visitGenerated\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDefaultValue\",\"url\":\"classes/MysqlQueryCompiler.html#visitDefaultValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelectModifier\",\"url\":\"classes/MysqlQueryCompiler.html#visitSelectModifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateType\",\"url\":\"classes/MysqlQueryCompiler.html#visitCreateType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropType\",\"url\":\"classes/MysqlQueryCompiler.html#visitDropType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitExplain\",\"url\":\"classes/MysqlQueryCompiler.html#visitExplain\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDefaultInsertValue\",\"url\":\"classes/MysqlQueryCompiler.html#visitDefaultInsertValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAggregateFunction\",\"url\":\"classes/MysqlQueryCompiler.html#visitAggregateFunction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOver\",\"url\":\"classes/MysqlQueryCompiler.html#visitOver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPartitionBy\",\"url\":\"classes/MysqlQueryCompiler.html#visitPartitionBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPartitionByItem\",\"url\":\"classes/MysqlQueryCompiler.html#visitPartitionByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitBinaryOperation\",\"url\":\"classes/MysqlQueryCompiler.html#visitBinaryOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUnaryOperation\",\"url\":\"classes/MysqlQueryCompiler.html#visitUnaryOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"isMinusOperator\",\"url\":\"classes/MysqlQueryCompiler.html#isMinusOperator\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUsing\",\"url\":\"classes/MysqlQueryCompiler.html#visitUsing\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitFunction\",\"url\":\"classes/MysqlQueryCompiler.html#visitFunction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCase\",\"url\":\"classes/MysqlQueryCompiler.html#visitCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitWhen\",\"url\":\"classes/MysqlQueryCompiler.html#visitWhen\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"append\",\"url\":\"classes/MysqlQueryCompiler.html#append\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"appendValue\",\"url\":\"classes/MysqlQueryCompiler.html#appendValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"addParameter\",\"url\":\"classes/MysqlQueryCompiler.html#addParameter\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"appendImmediateValue\",\"url\":\"classes/MysqlQueryCompiler.html#appendImmediateValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":1024,\"name\":\"nodeStack\",\"url\":\"classes/MysqlQueryCompiler.html#nodeStack\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":262144,\"name\":\"parentNode\",\"url\":\"classes/MysqlQueryCompiler.html#parentNode\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":2048,\"name\":\"visitNode\",\"url\":\"classes/MysqlQueryCompiler.html#visitNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"MysqlQueryCompiler\"},{\"kind\":128,\"name\":\"MysqlIntrospector\",\"url\":\"classes/MysqlIntrospector.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/MysqlIntrospector.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"MysqlIntrospector\"},{\"kind\":2048,\"name\":\"getSchemas\",\"url\":\"classes/MysqlIntrospector.html#getSchemas\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlIntrospector\"},{\"kind\":2048,\"name\":\"getTables\",\"url\":\"classes/MysqlIntrospector.html#getTables\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlIntrospector\"},{\"kind\":2048,\"name\":\"getMetadata\",\"url\":\"classes/MysqlIntrospector.html#getMetadata\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlIntrospector\"},{\"kind\":128,\"name\":\"MysqlAdapter\",\"url\":\"classes/MysqlAdapter.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/MysqlAdapter.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"MysqlAdapter\"},{\"kind\":262144,\"name\":\"supportsTransactionalDdl\",\"url\":\"classes/MysqlAdapter.html#supportsTransactionalDdl\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"MysqlAdapter\"},{\"kind\":262144,\"name\":\"supportsReturning\",\"url\":\"classes/MysqlAdapter.html#supportsReturning\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"MysqlAdapter\"},{\"kind\":2048,\"name\":\"acquireMigrationLock\",\"url\":\"classes/MysqlAdapter.html#acquireMigrationLock\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlAdapter\"},{\"kind\":2048,\"name\":\"releaseMigrationLock\",\"url\":\"classes/MysqlAdapter.html#releaseMigrationLock\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"MysqlAdapter\"},{\"kind\":128,\"name\":\"PostgresDriver\",\"url\":\"classes/PostgresDriver.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/PostgresDriver.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"PostgresDriver\"},{\"kind\":2048,\"name\":\"init\",\"url\":\"classes/PostgresDriver.html#init\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresDriver\"},{\"kind\":2048,\"name\":\"acquireConnection\",\"url\":\"classes/PostgresDriver.html#acquireConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresDriver\"},{\"kind\":2048,\"name\":\"beginTransaction\",\"url\":\"classes/PostgresDriver.html#beginTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresDriver\"},{\"kind\":2048,\"name\":\"commitTransaction\",\"url\":\"classes/PostgresDriver.html#commitTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresDriver\"},{\"kind\":2048,\"name\":\"rollbackTransaction\",\"url\":\"classes/PostgresDriver.html#rollbackTransaction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresDriver\"},{\"kind\":2048,\"name\":\"releaseConnection\",\"url\":\"classes/PostgresDriver.html#releaseConnection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresDriver\"},{\"kind\":2048,\"name\":\"destroy\",\"url\":\"classes/PostgresDriver.html#destroy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresDriver\"},{\"kind\":256,\"name\":\"PostgresDialectConfig\",\"url\":\"interfaces/PostgresDialectConfig.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"pool\",\"url\":\"interfaces/PostgresDialectConfig.html#pool\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PostgresDialectConfig\"},{\"kind\":1024,\"name\":\"cursor\",\"url\":\"interfaces/PostgresDialectConfig.html#cursor\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PostgresDialectConfig\"},{\"kind\":1024,\"name\":\"onCreateConnection\",\"url\":\"interfaces/PostgresDialectConfig.html#onCreateConnection\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PostgresDialectConfig\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/PostgresDialectConfig.html#onCreateConnection.__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-property\",\"parent\":\"PostgresDialectConfig.onCreateConnection\"},{\"kind\":256,\"name\":\"PostgresPool\",\"url\":\"interfaces/PostgresPool.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"connect\",\"url\":\"interfaces/PostgresPool.html#connect\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"PostgresPool\"},{\"kind\":2048,\"name\":\"end\",\"url\":\"interfaces/PostgresPool.html#end\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"PostgresPool\"},{\"kind\":256,\"name\":\"PostgresPoolClient\",\"url\":\"interfaces/PostgresPoolClient.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"query\",\"url\":\"interfaces/PostgresPoolClient.html#query\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"PostgresPoolClient\"},{\"kind\":2048,\"name\":\"release\",\"url\":\"interfaces/PostgresPoolClient.html#release\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"PostgresPoolClient\"},{\"kind\":256,\"name\":\"PostgresCursor\",\"url\":\"interfaces/PostgresCursor.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"read\",\"url\":\"interfaces/PostgresCursor.html#read\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"PostgresCursor\"},{\"kind\":2048,\"name\":\"close\",\"url\":\"interfaces/PostgresCursor.html#close\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"PostgresCursor\"},{\"kind\":4194304,\"name\":\"PostgresCursorConstructor\",\"url\":\"types/PostgresCursorConstructor.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":512,\"name\":\"__type\",\"url\":\"types/PostgresCursorConstructor.html#__type\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-type-alias\",\"parent\":\"PostgresCursorConstructor\"},{\"kind\":256,\"name\":\"PostgresQueryResult\",\"url\":\"interfaces/PostgresQueryResult.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"command\",\"url\":\"interfaces/PostgresQueryResult.html#command\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PostgresQueryResult\"},{\"kind\":1024,\"name\":\"rowCount\",\"url\":\"interfaces/PostgresQueryResult.html#rowCount\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PostgresQueryResult\"},{\"kind\":1024,\"name\":\"rows\",\"url\":\"interfaces/PostgresQueryResult.html#rows\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PostgresQueryResult\"},{\"kind\":256,\"name\":\"PostgresStream\",\"url\":\"interfaces/PostgresStream.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"[asyncIterator]\",\"url\":\"interfaces/PostgresStream.html#_asyncIterator_\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"PostgresStream\"},{\"kind\":128,\"name\":\"PostgresDialect\",\"url\":\"classes/PostgresDialect.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/PostgresDialect.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"PostgresDialect\"},{\"kind\":2048,\"name\":\"createDriver\",\"url\":\"classes/PostgresDialect.html#createDriver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresDialect\"},{\"kind\":2048,\"name\":\"createQueryCompiler\",\"url\":\"classes/PostgresDialect.html#createQueryCompiler\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresDialect\"},{\"kind\":2048,\"name\":\"createAdapter\",\"url\":\"classes/PostgresDialect.html#createAdapter\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresDialect\"},{\"kind\":2048,\"name\":\"createIntrospector\",\"url\":\"classes/PostgresDialect.html#createIntrospector\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"PostgresDialect\"},{\"kind\":128,\"name\":\"SqliteQueryCompiler\",\"url\":\"classes/SqliteQueryCompiler.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/SqliteQueryCompiler.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"getCurrentParameterPlaceholder\",\"url\":\"classes/SqliteQueryCompiler.html#getCurrentParameterPlaceholder\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"getLeftExplainOptionsWrapper\",\"url\":\"classes/SqliteQueryCompiler.html#getLeftExplainOptionsWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"getRightExplainOptionsWrapper\",\"url\":\"classes/SqliteQueryCompiler.html#getRightExplainOptionsWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"getLeftIdentifierWrapper\",\"url\":\"classes/SqliteQueryCompiler.html#getLeftIdentifierWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"getRightIdentifierWrapper\",\"url\":\"classes/SqliteQueryCompiler.html#getRightIdentifierWrapper\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"getAutoIncrement\",\"url\":\"classes/SqliteQueryCompiler.html#getAutoIncrement\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"sanitizeIdentifier\",\"url\":\"classes/SqliteQueryCompiler.html#sanitizeIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDefaultInsertValue\",\"url\":\"classes/SqliteQueryCompiler.html#visitDefaultInsertValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":262144,\"name\":\"numParameters\",\"url\":\"classes/SqliteQueryCompiler.html#numParameters\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"compileQuery\",\"url\":\"classes/SqliteQueryCompiler.html#compileQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"getSql\",\"url\":\"classes/SqliteQueryCompiler.html#getSql\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelectQuery\",\"url\":\"classes/SqliteQueryCompiler.html#visitSelectQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitFrom\",\"url\":\"classes/SqliteQueryCompiler.html#visitFrom\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelection\",\"url\":\"classes/SqliteQueryCompiler.html#visitSelection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitColumn\",\"url\":\"classes/SqliteQueryCompiler.html#visitColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"compileDistinctOn\",\"url\":\"classes/SqliteQueryCompiler.html#compileDistinctOn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"compileList\",\"url\":\"classes/SqliteQueryCompiler.html#compileList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitWhere\",\"url\":\"classes/SqliteQueryCompiler.html#visitWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitHaving\",\"url\":\"classes/SqliteQueryCompiler.html#visitHaving\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitInsertQuery\",\"url\":\"classes/SqliteQueryCompiler.html#visitInsertQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitValues\",\"url\":\"classes/SqliteQueryCompiler.html#visitValues\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDeleteQuery\",\"url\":\"classes/SqliteQueryCompiler.html#visitDeleteQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitReturning\",\"url\":\"classes/SqliteQueryCompiler.html#visitReturning\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAlias\",\"url\":\"classes/SqliteQueryCompiler.html#visitAlias\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitReference\",\"url\":\"classes/SqliteQueryCompiler.html#visitReference\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelectAll\",\"url\":\"classes/SqliteQueryCompiler.html#visitSelectAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitIdentifier\",\"url\":\"classes/SqliteQueryCompiler.html#visitIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"compileUnwrappedIdentifier\",\"url\":\"classes/SqliteQueryCompiler.html#compileUnwrappedIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAnd\",\"url\":\"classes/SqliteQueryCompiler.html#visitAnd\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOr\",\"url\":\"classes/SqliteQueryCompiler.html#visitOr\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitValue\",\"url\":\"classes/SqliteQueryCompiler.html#visitValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitValueList\",\"url\":\"classes/SqliteQueryCompiler.html#visitValueList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPrimitiveValueList\",\"url\":\"classes/SqliteQueryCompiler.html#visitPrimitiveValueList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitParens\",\"url\":\"classes/SqliteQueryCompiler.html#visitParens\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitJoin\",\"url\":\"classes/SqliteQueryCompiler.html#visitJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOn\",\"url\":\"classes/SqliteQueryCompiler.html#visitOn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitRaw\",\"url\":\"classes/SqliteQueryCompiler.html#visitRaw\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOperator\",\"url\":\"classes/SqliteQueryCompiler.html#visitOperator\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitTable\",\"url\":\"classes/SqliteQueryCompiler.html#visitTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSchemableIdentifier\",\"url\":\"classes/SqliteQueryCompiler.html#visitSchemableIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateTable\",\"url\":\"classes/SqliteQueryCompiler.html#visitCreateTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitColumnDefinition\",\"url\":\"classes/SqliteQueryCompiler.html#visitColumnDefinition\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitReferences\",\"url\":\"classes/SqliteQueryCompiler.html#visitReferences\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropTable\",\"url\":\"classes/SqliteQueryCompiler.html#visitDropTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDataType\",\"url\":\"classes/SqliteQueryCompiler.html#visitDataType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOrderBy\",\"url\":\"classes/SqliteQueryCompiler.html#visitOrderBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOrderByItem\",\"url\":\"classes/SqliteQueryCompiler.html#visitOrderByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitGroupBy\",\"url\":\"classes/SqliteQueryCompiler.html#visitGroupBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitGroupByItem\",\"url\":\"classes/SqliteQueryCompiler.html#visitGroupByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUpdateQuery\",\"url\":\"classes/SqliteQueryCompiler.html#visitUpdateQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitColumnUpdate\",\"url\":\"classes/SqliteQueryCompiler.html#visitColumnUpdate\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitLimit\",\"url\":\"classes/SqliteQueryCompiler.html#visitLimit\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOffset\",\"url\":\"classes/SqliteQueryCompiler.html#visitOffset\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOnConflict\",\"url\":\"classes/SqliteQueryCompiler.html#visitOnConflict\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOnDuplicateKey\",\"url\":\"classes/SqliteQueryCompiler.html#visitOnDuplicateKey\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateIndex\",\"url\":\"classes/SqliteQueryCompiler.html#visitCreateIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropIndex\",\"url\":\"classes/SqliteQueryCompiler.html#visitDropIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateSchema\",\"url\":\"classes/SqliteQueryCompiler.html#visitCreateSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropSchema\",\"url\":\"classes/SqliteQueryCompiler.html#visitDropSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPrimaryKeyConstraint\",\"url\":\"classes/SqliteQueryCompiler.html#visitPrimaryKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUniqueConstraint\",\"url\":\"classes/SqliteQueryCompiler.html#visitUniqueConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCheckConstraint\",\"url\":\"classes/SqliteQueryCompiler.html#visitCheckConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitForeignKeyConstraint\",\"url\":\"classes/SqliteQueryCompiler.html#visitForeignKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitList\",\"url\":\"classes/SqliteQueryCompiler.html#visitList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitWith\",\"url\":\"classes/SqliteQueryCompiler.html#visitWith\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCommonTableExpression\",\"url\":\"classes/SqliteQueryCompiler.html#visitCommonTableExpression\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCommonTableExpressionName\",\"url\":\"classes/SqliteQueryCompiler.html#visitCommonTableExpressionName\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAlterTable\",\"url\":\"classes/SqliteQueryCompiler.html#visitAlterTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAddColumn\",\"url\":\"classes/SqliteQueryCompiler.html#visitAddColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitRenameColumn\",\"url\":\"classes/SqliteQueryCompiler.html#visitRenameColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropColumn\",\"url\":\"classes/SqliteQueryCompiler.html#visitDropColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAlterColumn\",\"url\":\"classes/SqliteQueryCompiler.html#visitAlterColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitModifyColumn\",\"url\":\"classes/SqliteQueryCompiler.html#visitModifyColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAddConstraint\",\"url\":\"classes/SqliteQueryCompiler.html#visitAddConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropConstraint\",\"url\":\"classes/SqliteQueryCompiler.html#visitDropConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSetOperation\",\"url\":\"classes/SqliteQueryCompiler.html#visitSetOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateView\",\"url\":\"classes/SqliteQueryCompiler.html#visitCreateView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropView\",\"url\":\"classes/SqliteQueryCompiler.html#visitDropView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitGenerated\",\"url\":\"classes/SqliteQueryCompiler.html#visitGenerated\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDefaultValue\",\"url\":\"classes/SqliteQueryCompiler.html#visitDefaultValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitSelectModifier\",\"url\":\"classes/SqliteQueryCompiler.html#visitSelectModifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCreateType\",\"url\":\"classes/SqliteQueryCompiler.html#visitCreateType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitDropType\",\"url\":\"classes/SqliteQueryCompiler.html#visitDropType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitExplain\",\"url\":\"classes/SqliteQueryCompiler.html#visitExplain\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitAggregateFunction\",\"url\":\"classes/SqliteQueryCompiler.html#visitAggregateFunction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitOver\",\"url\":\"classes/SqliteQueryCompiler.html#visitOver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPartitionBy\",\"url\":\"classes/SqliteQueryCompiler.html#visitPartitionBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitPartitionByItem\",\"url\":\"classes/SqliteQueryCompiler.html#visitPartitionByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitBinaryOperation\",\"url\":\"classes/SqliteQueryCompiler.html#visitBinaryOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUnaryOperation\",\"url\":\"classes/SqliteQueryCompiler.html#visitUnaryOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"isMinusOperator\",\"url\":\"classes/SqliteQueryCompiler.html#isMinusOperator\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitUsing\",\"url\":\"classes/SqliteQueryCompiler.html#visitUsing\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitFunction\",\"url\":\"classes/SqliteQueryCompiler.html#visitFunction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitCase\",\"url\":\"classes/SqliteQueryCompiler.html#visitCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitWhen\",\"url\":\"classes/SqliteQueryCompiler.html#visitWhen\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"append\",\"url\":\"classes/SqliteQueryCompiler.html#append\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"appendValue\",\"url\":\"classes/SqliteQueryCompiler.html#appendValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"getExplainOptionAssignment\",\"url\":\"classes/SqliteQueryCompiler.html#getExplainOptionAssignment\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"getExplainOptionsDelimiter\",\"url\":\"classes/SqliteQueryCompiler.html#getExplainOptionsDelimiter\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"addParameter\",\"url\":\"classes/SqliteQueryCompiler.html#addParameter\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"appendImmediateValue\",\"url\":\"classes/SqliteQueryCompiler.html#appendImmediateValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":1024,\"name\":\"nodeStack\",\"url\":\"classes/SqliteQueryCompiler.html#nodeStack\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":262144,\"name\":\"parentNode\",\"url\":\"classes/SqliteQueryCompiler.html#parentNode\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":2048,\"name\":\"visitNode\",\"url\":\"classes/SqliteQueryCompiler.html#visitNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"SqliteQueryCompiler\"},{\"kind\":128,\"name\":\"SqliteIntrospector\",\"url\":\"classes/SqliteIntrospector.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/SqliteIntrospector.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"SqliteIntrospector\"},{\"kind\":2048,\"name\":\"getSchemas\",\"url\":\"classes/SqliteIntrospector.html#getSchemas\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteIntrospector\"},{\"kind\":2048,\"name\":\"getTables\",\"url\":\"classes/SqliteIntrospector.html#getTables\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteIntrospector\"},{\"kind\":2048,\"name\":\"getMetadata\",\"url\":\"classes/SqliteIntrospector.html#getMetadata\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteIntrospector\"},{\"kind\":128,\"name\":\"SqliteAdapter\",\"url\":\"classes/SqliteAdapter.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/SqliteAdapter.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"SqliteAdapter\"},{\"kind\":262144,\"name\":\"supportsTransactionalDdl\",\"url\":\"classes/SqliteAdapter.html#supportsTransactionalDdl\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"SqliteAdapter\"},{\"kind\":262144,\"name\":\"supportsReturning\",\"url\":\"classes/SqliteAdapter.html#supportsReturning\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"SqliteAdapter\"},{\"kind\":2048,\"name\":\"acquireMigrationLock\",\"url\":\"classes/SqliteAdapter.html#acquireMigrationLock\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteAdapter\"},{\"kind\":2048,\"name\":\"releaseMigrationLock\",\"url\":\"classes/SqliteAdapter.html#releaseMigrationLock\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"SqliteAdapter\"},{\"kind\":4194304,\"name\":\"RootOperationNode\",\"url\":\"types/RootOperationNode.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"QueryCompiler\",\"url\":\"interfaces/QueryCompiler.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"compileQuery\",\"url\":\"interfaces/QueryCompiler.html#compileQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"QueryCompiler\"},{\"kind\":32,\"name\":\"DEFAULT_MIGRATION_TABLE\",\"url\":\"variables/DEFAULT_MIGRATION_TABLE.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":32,\"name\":\"DEFAULT_MIGRATION_LOCK_TABLE\",\"url\":\"variables/DEFAULT_MIGRATION_LOCK_TABLE.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":32,\"name\":\"MIGRATION_LOCK_ID\",\"url\":\"variables/MIGRATION_LOCK_ID.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":32,\"name\":\"NO_MIGRATIONS\",\"url\":\"variables/NO_MIGRATIONS.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":256,\"name\":\"Migration\",\"url\":\"interfaces/Migration.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"up\",\"url\":\"interfaces/Migration.html#up\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Migration\"},{\"kind\":2048,\"name\":\"down\",\"url\":\"interfaces/Migration.html#down\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Migration\"},{\"kind\":128,\"name\":\"Migrator\",\"url\":\"classes/Migrator.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/Migrator.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"Migrator\"},{\"kind\":2048,\"name\":\"getMigrations\",\"url\":\"classes/Migrator.html#getMigrations\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Migrator\"},{\"kind\":2048,\"name\":\"migrateToLatest\",\"url\":\"classes/Migrator.html#migrateToLatest\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Migrator\"},{\"kind\":2048,\"name\":\"migrateTo\",\"url\":\"classes/Migrator.html#migrateTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Migrator\"},{\"kind\":2048,\"name\":\"migrateUp\",\"url\":\"classes/Migrator.html#migrateUp\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Migrator\"},{\"kind\":2048,\"name\":\"migrateDown\",\"url\":\"classes/Migrator.html#migrateDown\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Migrator\"},{\"kind\":256,\"name\":\"MigratorProps\",\"url\":\"interfaces/MigratorProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"db\",\"url\":\"interfaces/MigratorProps.html#db\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigratorProps\"},{\"kind\":1024,\"name\":\"provider\",\"url\":\"interfaces/MigratorProps.html#provider\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigratorProps\"},{\"kind\":1024,\"name\":\"migrationTableName\",\"url\":\"interfaces/MigratorProps.html#migrationTableName\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigratorProps\"},{\"kind\":1024,\"name\":\"migrationLockTableName\",\"url\":\"interfaces/MigratorProps.html#migrationLockTableName\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigratorProps\"},{\"kind\":1024,\"name\":\"migrationTableSchema\",\"url\":\"interfaces/MigratorProps.html#migrationTableSchema\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigratorProps\"},{\"kind\":256,\"name\":\"MigrationResultSet\",\"url\":\"interfaces/MigrationResultSet.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"error\",\"url\":\"interfaces/MigrationResultSet.html#error\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigrationResultSet\"},{\"kind\":1024,\"name\":\"results\",\"url\":\"interfaces/MigrationResultSet.html#results\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigrationResultSet\"},{\"kind\":256,\"name\":\"MigrationResult\",\"url\":\"interfaces/MigrationResult.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"migrationName\",\"url\":\"interfaces/MigrationResult.html#migrationName\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigrationResult\"},{\"kind\":1024,\"name\":\"direction\",\"url\":\"interfaces/MigrationResult.html#direction\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigrationResult\"},{\"kind\":1024,\"name\":\"status\",\"url\":\"interfaces/MigrationResult.html#status\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigrationResult\"},{\"kind\":256,\"name\":\"MigrationProvider\",\"url\":\"interfaces/MigrationProvider.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"getMigrations\",\"url\":\"interfaces/MigrationProvider.html#getMigrations\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"MigrationProvider\"},{\"kind\":256,\"name\":\"NoMigrations\",\"url\":\"interfaces/NoMigrations.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"__noMigrations__\",\"url\":\"interfaces/NoMigrations.html#__noMigrations__\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"NoMigrations\"},{\"kind\":256,\"name\":\"MigrationInfo\",\"url\":\"interfaces/MigrationInfo.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/MigrationInfo.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigrationInfo\"},{\"kind\":1024,\"name\":\"migration\",\"url\":\"interfaces/MigrationInfo.html#migration\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigrationInfo\"},{\"kind\":1024,\"name\":\"executedAt\",\"url\":\"interfaces/MigrationInfo.html#executedAt\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"MigrationInfo\"},{\"kind\":128,\"name\":\"FileMigrationProvider\",\"url\":\"classes/FileMigrationProvider.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/FileMigrationProvider.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"FileMigrationProvider\"},{\"kind\":2048,\"name\":\"getMigrations\",\"url\":\"classes/FileMigrationProvider.html#getMigrations\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"FileMigrationProvider\"},{\"kind\":256,\"name\":\"FileMigrationProviderFS\",\"url\":\"interfaces/FileMigrationProviderFS.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"readdir\",\"url\":\"interfaces/FileMigrationProviderFS.html#readdir\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"FileMigrationProviderFS\"},{\"kind\":256,\"name\":\"FileMigrationProviderPath\",\"url\":\"interfaces/FileMigrationProviderPath.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"join\",\"url\":\"interfaces/FileMigrationProviderPath.html#join\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"FileMigrationProviderPath\"},{\"kind\":256,\"name\":\"FileMigrationProviderProps\",\"url\":\"interfaces/FileMigrationProviderProps.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"fs\",\"url\":\"interfaces/FileMigrationProviderProps.html#fs\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"FileMigrationProviderProps\"},{\"kind\":1024,\"name\":\"path\",\"url\":\"interfaces/FileMigrationProviderProps.html#path\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"FileMigrationProviderProps\"},{\"kind\":1024,\"name\":\"migrationFolder\",\"url\":\"interfaces/FileMigrationProviderProps.html#migrationFolder\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"FileMigrationProviderProps\"},{\"kind\":256,\"name\":\"KyselyPlugin\",\"url\":\"interfaces/KyselyPlugin.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"transformQuery\",\"url\":\"interfaces/KyselyPlugin.html#transformQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"KyselyPlugin\"},{\"kind\":2048,\"name\":\"transformResult\",\"url\":\"interfaces/KyselyPlugin.html#transformResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"KyselyPlugin\"},{\"kind\":256,\"name\":\"PluginTransformQueryArgs\",\"url\":\"interfaces/PluginTransformQueryArgs.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/PluginTransformQueryArgs.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PluginTransformQueryArgs\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/PluginTransformQueryArgs.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PluginTransformQueryArgs\"},{\"kind\":256,\"name\":\"PluginTransformResultArgs\",\"url\":\"interfaces/PluginTransformResultArgs.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"queryId\",\"url\":\"interfaces/PluginTransformResultArgs.html#queryId\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PluginTransformResultArgs\"},{\"kind\":1024,\"name\":\"result\",\"url\":\"interfaces/PluginTransformResultArgs.html#result\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PluginTransformResultArgs\"},{\"kind\":256,\"name\":\"CamelCasePluginOptions\",\"url\":\"interfaces/CamelCasePluginOptions.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"upperCase\",\"url\":\"interfaces/CamelCasePluginOptions.html#upperCase\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CamelCasePluginOptions\"},{\"kind\":1024,\"name\":\"underscoreBeforeDigits\",\"url\":\"interfaces/CamelCasePluginOptions.html#underscoreBeforeDigits\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CamelCasePluginOptions\"},{\"kind\":1024,\"name\":\"underscoreBetweenUppercaseLetters\",\"url\":\"interfaces/CamelCasePluginOptions.html#underscoreBetweenUppercaseLetters\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CamelCasePluginOptions\"},{\"kind\":1024,\"name\":\"maintainNestedObjectKeys\",\"url\":\"interfaces/CamelCasePluginOptions.html#maintainNestedObjectKeys\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CamelCasePluginOptions\"},{\"kind\":128,\"name\":\"CamelCasePlugin\",\"url\":\"classes/CamelCasePlugin.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/CamelCasePlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"CamelCasePlugin\"},{\"kind\":1024,\"name\":\"opt\",\"url\":\"classes/CamelCasePlugin.html#opt\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"CamelCasePlugin\"},{\"kind\":2048,\"name\":\"transformQuery\",\"url\":\"classes/CamelCasePlugin.html#transformQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CamelCasePlugin\"},{\"kind\":2048,\"name\":\"transformResult\",\"url\":\"classes/CamelCasePlugin.html#transformResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"CamelCasePlugin\"},{\"kind\":2048,\"name\":\"mapRow\",\"url\":\"classes/CamelCasePlugin.html#mapRow\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"CamelCasePlugin\"},{\"kind\":2048,\"name\":\"snakeCase\",\"url\":\"classes/CamelCasePlugin.html#snakeCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"CamelCasePlugin\"},{\"kind\":2048,\"name\":\"camelCase\",\"url\":\"classes/CamelCasePlugin.html#camelCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"CamelCasePlugin\"},{\"kind\":128,\"name\":\"DeduplicateJoinsPlugin\",\"url\":\"classes/DeduplicateJoinsPlugin.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/DeduplicateJoinsPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"DeduplicateJoinsPlugin\"},{\"kind\":2048,\"name\":\"transformQuery\",\"url\":\"classes/DeduplicateJoinsPlugin.html#transformQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeduplicateJoinsPlugin\"},{\"kind\":2048,\"name\":\"transformResult\",\"url\":\"classes/DeduplicateJoinsPlugin.html#transformResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"DeduplicateJoinsPlugin\"},{\"kind\":128,\"name\":\"WithSchemaPlugin\",\"url\":\"classes/WithSchemaPlugin.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/WithSchemaPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"WithSchemaPlugin\"},{\"kind\":2048,\"name\":\"transformQuery\",\"url\":\"classes/WithSchemaPlugin.html#transformQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WithSchemaPlugin\"},{\"kind\":2048,\"name\":\"transformResult\",\"url\":\"classes/WithSchemaPlugin.html#transformResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"WithSchemaPlugin\"},{\"kind\":256,\"name\":\"AddColumnNode\",\"url\":\"interfaces/AddColumnNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/AddColumnNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AddColumnNode\"},{\"kind\":1024,\"name\":\"column\",\"url\":\"interfaces/AddColumnNode.html#column\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AddColumnNode\"},{\"kind\":256,\"name\":\"AddConstraintNode\",\"url\":\"interfaces/AddConstraintNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/AddConstraintNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AddConstraintNode\"},{\"kind\":1024,\"name\":\"constraint\",\"url\":\"interfaces/AddConstraintNode.html#constraint\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AddConstraintNode\"},{\"kind\":256,\"name\":\"AliasNode\",\"url\":\"interfaces/AliasNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/AliasNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AliasNode\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/AliasNode.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AliasNode\"},{\"kind\":1024,\"name\":\"alias\",\"url\":\"interfaces/AliasNode.html#alias\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AliasNode\"},{\"kind\":4194304,\"name\":\"AlterColumnNodeProps\",\"url\":\"types/AlterColumnNodeProps.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"AlterColumnNode\",\"url\":\"interfaces/AlterColumnNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/AlterColumnNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterColumnNode\"},{\"kind\":1024,\"name\":\"column\",\"url\":\"interfaces/AlterColumnNode.html#column\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterColumnNode\"},{\"kind\":1024,\"name\":\"dataType\",\"url\":\"interfaces/AlterColumnNode.html#dataType\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterColumnNode\"},{\"kind\":1024,\"name\":\"dataTypeExpression\",\"url\":\"interfaces/AlterColumnNode.html#dataTypeExpression\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterColumnNode\"},{\"kind\":1024,\"name\":\"setDefault\",\"url\":\"interfaces/AlterColumnNode.html#setDefault\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterColumnNode\"},{\"kind\":1024,\"name\":\"dropDefault\",\"url\":\"interfaces/AlterColumnNode.html#dropDefault\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterColumnNode\"},{\"kind\":1024,\"name\":\"setNotNull\",\"url\":\"interfaces/AlterColumnNode.html#setNotNull\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterColumnNode\"},{\"kind\":1024,\"name\":\"dropNotNull\",\"url\":\"interfaces/AlterColumnNode.html#dropNotNull\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterColumnNode\"},{\"kind\":4194304,\"name\":\"AlterTableNodeTableProps\",\"url\":\"types/AlterTableNodeTableProps.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"AlterTableColumnAlterationNode\",\"url\":\"types/AlterTableColumnAlterationNode.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"AlterTableNode\",\"url\":\"interfaces/AlterTableNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/AlterTableNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterTableNode\"},{\"kind\":1024,\"name\":\"table\",\"url\":\"interfaces/AlterTableNode.html#table\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterTableNode\"},{\"kind\":1024,\"name\":\"renameTo\",\"url\":\"interfaces/AlterTableNode.html#renameTo\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterTableNode\"},{\"kind\":1024,\"name\":\"setSchema\",\"url\":\"interfaces/AlterTableNode.html#setSchema\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterTableNode\"},{\"kind\":1024,\"name\":\"columnAlterations\",\"url\":\"interfaces/AlterTableNode.html#columnAlterations\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterTableNode\"},{\"kind\":1024,\"name\":\"addConstraint\",\"url\":\"interfaces/AlterTableNode.html#addConstraint\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterTableNode\"},{\"kind\":1024,\"name\":\"dropConstraint\",\"url\":\"interfaces/AlterTableNode.html#dropConstraint\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AlterTableNode\"},{\"kind\":256,\"name\":\"AndNode\",\"url\":\"interfaces/AndNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/AndNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AndNode\"},{\"kind\":1024,\"name\":\"left\",\"url\":\"interfaces/AndNode.html#left\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AndNode\"},{\"kind\":1024,\"name\":\"right\",\"url\":\"interfaces/AndNode.html#right\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AndNode\"},{\"kind\":256,\"name\":\"CaseNode\",\"url\":\"interfaces/CaseNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/CaseNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CaseNode\"},{\"kind\":1024,\"name\":\"value\",\"url\":\"interfaces/CaseNode.html#value\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CaseNode\"},{\"kind\":1024,\"name\":\"when\",\"url\":\"interfaces/CaseNode.html#when\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CaseNode\"},{\"kind\":1024,\"name\":\"else\",\"url\":\"interfaces/CaseNode.html#else\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CaseNode\"},{\"kind\":1024,\"name\":\"isStatement\",\"url\":\"interfaces/CaseNode.html#isStatement\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CaseNode\"},{\"kind\":256,\"name\":\"CheckConstraintNode\",\"url\":\"interfaces/CheckConstraintNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/CheckConstraintNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CheckConstraintNode\"},{\"kind\":1024,\"name\":\"expression\",\"url\":\"interfaces/CheckConstraintNode.html#expression\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CheckConstraintNode\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/CheckConstraintNode.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CheckConstraintNode\"},{\"kind\":4194304,\"name\":\"ColumnDefinitionNodeProps\",\"url\":\"types/ColumnDefinitionNodeProps.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"ColumnDefinitionNode\",\"url\":\"interfaces/ColumnDefinitionNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ColumnDefinitionNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":1024,\"name\":\"column\",\"url\":\"interfaces/ColumnDefinitionNode.html#column\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":1024,\"name\":\"dataType\",\"url\":\"interfaces/ColumnDefinitionNode.html#dataType\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":1024,\"name\":\"references\",\"url\":\"interfaces/ColumnDefinitionNode.html#references\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":1024,\"name\":\"primaryKey\",\"url\":\"interfaces/ColumnDefinitionNode.html#primaryKey\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":1024,\"name\":\"autoIncrement\",\"url\":\"interfaces/ColumnDefinitionNode.html#autoIncrement\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":1024,\"name\":\"unique\",\"url\":\"interfaces/ColumnDefinitionNode.html#unique\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":1024,\"name\":\"notNull\",\"url\":\"interfaces/ColumnDefinitionNode.html#notNull\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":1024,\"name\":\"defaultTo\",\"url\":\"interfaces/ColumnDefinitionNode.html#defaultTo\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":1024,\"name\":\"check\",\"url\":\"interfaces/ColumnDefinitionNode.html#check\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":1024,\"name\":\"generated\",\"url\":\"interfaces/ColumnDefinitionNode.html#generated\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":1024,\"name\":\"unsigned\",\"url\":\"interfaces/ColumnDefinitionNode.html#unsigned\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":1024,\"name\":\"frontModifiers\",\"url\":\"interfaces/ColumnDefinitionNode.html#frontModifiers\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":1024,\"name\":\"endModifiers\",\"url\":\"interfaces/ColumnDefinitionNode.html#endModifiers\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnDefinitionNode\"},{\"kind\":256,\"name\":\"ColumnNode\",\"url\":\"interfaces/ColumnNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ColumnNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnNode\"},{\"kind\":1024,\"name\":\"column\",\"url\":\"interfaces/ColumnNode.html#column\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnNode\"},{\"kind\":256,\"name\":\"ColumnUpdateNode\",\"url\":\"interfaces/ColumnUpdateNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ColumnUpdateNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnUpdateNode\"},{\"kind\":1024,\"name\":\"column\",\"url\":\"interfaces/ColumnUpdateNode.html#column\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnUpdateNode\"},{\"kind\":1024,\"name\":\"value\",\"url\":\"interfaces/ColumnUpdateNode.html#value\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ColumnUpdateNode\"},{\"kind\":256,\"name\":\"CommonTableExpressionNode\",\"url\":\"interfaces/CommonTableExpressionNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/CommonTableExpressionNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CommonTableExpressionNode\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/CommonTableExpressionNode.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CommonTableExpressionNode\"},{\"kind\":1024,\"name\":\"expression\",\"url\":\"interfaces/CommonTableExpressionNode.html#expression\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CommonTableExpressionNode\"},{\"kind\":256,\"name\":\"CommonTableExpressionNameNode\",\"url\":\"interfaces/CommonTableExpressionNameNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/CommonTableExpressionNameNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CommonTableExpressionNameNode\"},{\"kind\":1024,\"name\":\"table\",\"url\":\"interfaces/CommonTableExpressionNameNode.html#table\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CommonTableExpressionNameNode\"},{\"kind\":1024,\"name\":\"columns\",\"url\":\"interfaces/CommonTableExpressionNameNode.html#columns\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CommonTableExpressionNameNode\"},{\"kind\":4194304,\"name\":\"ConstraintNode\",\"url\":\"types/ConstraintNode.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"CreateIndexNodeProps\",\"url\":\"types/CreateIndexNodeProps.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"IndexType\",\"url\":\"types/IndexType.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"CreateIndexNode\",\"url\":\"interfaces/CreateIndexNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/CreateIndexNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateIndexNode\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/CreateIndexNode.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateIndexNode\"},{\"kind\":1024,\"name\":\"table\",\"url\":\"interfaces/CreateIndexNode.html#table\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateIndexNode\"},{\"kind\":1024,\"name\":\"columns\",\"url\":\"interfaces/CreateIndexNode.html#columns\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateIndexNode\"},{\"kind\":1024,\"name\":\"unique\",\"url\":\"interfaces/CreateIndexNode.html#unique\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateIndexNode\"},{\"kind\":1024,\"name\":\"using\",\"url\":\"interfaces/CreateIndexNode.html#using\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateIndexNode\"},{\"kind\":1024,\"name\":\"ifNotExists\",\"url\":\"interfaces/CreateIndexNode.html#ifNotExists\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateIndexNode\"},{\"kind\":1024,\"name\":\"where\",\"url\":\"interfaces/CreateIndexNode.html#where\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateIndexNode\"},{\"kind\":4194304,\"name\":\"CreateSchemaNodeParams\",\"url\":\"types/CreateSchemaNodeParams.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"CreateSchemaNode\",\"url\":\"interfaces/CreateSchemaNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/CreateSchemaNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateSchemaNode\"},{\"kind\":1024,\"name\":\"schema\",\"url\":\"interfaces/CreateSchemaNode.html#schema\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateSchemaNode\"},{\"kind\":1024,\"name\":\"ifNotExists\",\"url\":\"interfaces/CreateSchemaNode.html#ifNotExists\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateSchemaNode\"},{\"kind\":32,\"name\":\"ON_COMMIT_ACTIONS\",\"url\":\"variables/ON_COMMIT_ACTIONS.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":4194304,\"name\":\"OnCommitAction\",\"url\":\"types/OnCommitAction.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"CreateTableNodeParams\",\"url\":\"types/CreateTableNodeParams.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"CreateTableNode\",\"url\":\"interfaces/CreateTableNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/CreateTableNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTableNode\"},{\"kind\":1024,\"name\":\"table\",\"url\":\"interfaces/CreateTableNode.html#table\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTableNode\"},{\"kind\":1024,\"name\":\"columns\",\"url\":\"interfaces/CreateTableNode.html#columns\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTableNode\"},{\"kind\":1024,\"name\":\"constraints\",\"url\":\"interfaces/CreateTableNode.html#constraints\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTableNode\"},{\"kind\":1024,\"name\":\"temporary\",\"url\":\"interfaces/CreateTableNode.html#temporary\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTableNode\"},{\"kind\":1024,\"name\":\"ifNotExists\",\"url\":\"interfaces/CreateTableNode.html#ifNotExists\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTableNode\"},{\"kind\":1024,\"name\":\"onCommit\",\"url\":\"interfaces/CreateTableNode.html#onCommit\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTableNode\"},{\"kind\":1024,\"name\":\"frontModifiers\",\"url\":\"interfaces/CreateTableNode.html#frontModifiers\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTableNode\"},{\"kind\":1024,\"name\":\"endModifiers\",\"url\":\"interfaces/CreateTableNode.html#endModifiers\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTableNode\"},{\"kind\":4194304,\"name\":\"CreateTypeNodeParams\",\"url\":\"types/CreateTypeNodeParams.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"CreateTypeNode\",\"url\":\"interfaces/CreateTypeNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/CreateTypeNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTypeNode\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/CreateTypeNode.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTypeNode\"},{\"kind\":1024,\"name\":\"enum\",\"url\":\"interfaces/CreateTypeNode.html#enum\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateTypeNode\"},{\"kind\":4194304,\"name\":\"CreateViewNodeParams\",\"url\":\"types/CreateViewNodeParams.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"CreateViewNode\",\"url\":\"interfaces/CreateViewNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/CreateViewNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateViewNode\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/CreateViewNode.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateViewNode\"},{\"kind\":1024,\"name\":\"temporary\",\"url\":\"interfaces/CreateViewNode.html#temporary\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateViewNode\"},{\"kind\":1024,\"name\":\"materialized\",\"url\":\"interfaces/CreateViewNode.html#materialized\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateViewNode\"},{\"kind\":1024,\"name\":\"orReplace\",\"url\":\"interfaces/CreateViewNode.html#orReplace\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateViewNode\"},{\"kind\":1024,\"name\":\"ifNotExists\",\"url\":\"interfaces/CreateViewNode.html#ifNotExists\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateViewNode\"},{\"kind\":1024,\"name\":\"columns\",\"url\":\"interfaces/CreateViewNode.html#columns\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateViewNode\"},{\"kind\":1024,\"name\":\"as\",\"url\":\"interfaces/CreateViewNode.html#as\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"CreateViewNode\"},{\"kind\":4194304,\"name\":\"ColumnDataType\",\"url\":\"types/ColumnDataType.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"DataTypeParams\",\"url\":\"types/DataTypeParams.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"DataTypeNode\",\"url\":\"interfaces/DataTypeNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/DataTypeNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DataTypeNode\"},{\"kind\":1024,\"name\":\"dataType\",\"url\":\"interfaces/DataTypeNode.html#dataType\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DataTypeNode\"},{\"kind\":256,\"name\":\"DefaultValueNode\",\"url\":\"interfaces/DefaultValueNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/DefaultValueNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DefaultValueNode\"},{\"kind\":1024,\"name\":\"defaultValue\",\"url\":\"interfaces/DefaultValueNode.html#defaultValue\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DefaultValueNode\"},{\"kind\":256,\"name\":\"DeleteQueryNode\",\"url\":\"interfaces/DeleteQueryNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/DeleteQueryNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DeleteQueryNode\"},{\"kind\":1024,\"name\":\"from\",\"url\":\"interfaces/DeleteQueryNode.html#from\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DeleteQueryNode\"},{\"kind\":1024,\"name\":\"using\",\"url\":\"interfaces/DeleteQueryNode.html#using\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DeleteQueryNode\"},{\"kind\":1024,\"name\":\"joins\",\"url\":\"interfaces/DeleteQueryNode.html#joins\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DeleteQueryNode\"},{\"kind\":1024,\"name\":\"where\",\"url\":\"interfaces/DeleteQueryNode.html#where\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DeleteQueryNode\"},{\"kind\":1024,\"name\":\"returning\",\"url\":\"interfaces/DeleteQueryNode.html#returning\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DeleteQueryNode\"},{\"kind\":1024,\"name\":\"with\",\"url\":\"interfaces/DeleteQueryNode.html#with\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DeleteQueryNode\"},{\"kind\":1024,\"name\":\"orderBy\",\"url\":\"interfaces/DeleteQueryNode.html#orderBy\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DeleteQueryNode\"},{\"kind\":1024,\"name\":\"limit\",\"url\":\"interfaces/DeleteQueryNode.html#limit\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DeleteQueryNode\"},{\"kind\":1024,\"name\":\"explain\",\"url\":\"interfaces/DeleteQueryNode.html#explain\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DeleteQueryNode\"},{\"kind\":256,\"name\":\"DropColumnNode\",\"url\":\"interfaces/DropColumnNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/DropColumnNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropColumnNode\"},{\"kind\":1024,\"name\":\"column\",\"url\":\"interfaces/DropColumnNode.html#column\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropColumnNode\"},{\"kind\":4194304,\"name\":\"DropConstraintNodeProps\",\"url\":\"types/DropConstraintNodeProps.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"DropConstraintNode\",\"url\":\"interfaces/DropConstraintNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/DropConstraintNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropConstraintNode\"},{\"kind\":1024,\"name\":\"constraintName\",\"url\":\"interfaces/DropConstraintNode.html#constraintName\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropConstraintNode\"},{\"kind\":1024,\"name\":\"ifExists\",\"url\":\"interfaces/DropConstraintNode.html#ifExists\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropConstraintNode\"},{\"kind\":1024,\"name\":\"modifier\",\"url\":\"interfaces/DropConstraintNode.html#modifier\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropConstraintNode\"},{\"kind\":4194304,\"name\":\"DropIndexNodeProps\",\"url\":\"types/DropIndexNodeProps.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"DropIndexNode\",\"url\":\"interfaces/DropIndexNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/DropIndexNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropIndexNode\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/DropIndexNode.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropIndexNode\"},{\"kind\":1024,\"name\":\"table\",\"url\":\"interfaces/DropIndexNode.html#table\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropIndexNode\"},{\"kind\":1024,\"name\":\"ifExists\",\"url\":\"interfaces/DropIndexNode.html#ifExists\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropIndexNode\"},{\"kind\":1024,\"name\":\"cascade\",\"url\":\"interfaces/DropIndexNode.html#cascade\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropIndexNode\"},{\"kind\":4194304,\"name\":\"DropSchemaNodeParams\",\"url\":\"types/DropSchemaNodeParams.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"DropSchemaNode\",\"url\":\"interfaces/DropSchemaNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/DropSchemaNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropSchemaNode\"},{\"kind\":1024,\"name\":\"schema\",\"url\":\"interfaces/DropSchemaNode.html#schema\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropSchemaNode\"},{\"kind\":1024,\"name\":\"ifExists\",\"url\":\"interfaces/DropSchemaNode.html#ifExists\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropSchemaNode\"},{\"kind\":1024,\"name\":\"cascade\",\"url\":\"interfaces/DropSchemaNode.html#cascade\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropSchemaNode\"},{\"kind\":4194304,\"name\":\"DropTablexNodeParams\",\"url\":\"types/DropTablexNodeParams.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"DropTableNode\",\"url\":\"interfaces/DropTableNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/DropTableNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropTableNode\"},{\"kind\":1024,\"name\":\"table\",\"url\":\"interfaces/DropTableNode.html#table\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropTableNode\"},{\"kind\":1024,\"name\":\"ifExists\",\"url\":\"interfaces/DropTableNode.html#ifExists\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropTableNode\"},{\"kind\":1024,\"name\":\"cascade\",\"url\":\"interfaces/DropTableNode.html#cascade\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropTableNode\"},{\"kind\":4194304,\"name\":\"DropTypeNodeParams\",\"url\":\"types/DropTypeNodeParams.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"DropTypeNode\",\"url\":\"interfaces/DropTypeNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/DropTypeNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropTypeNode\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/DropTypeNode.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropTypeNode\"},{\"kind\":1024,\"name\":\"ifExists\",\"url\":\"interfaces/DropTypeNode.html#ifExists\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropTypeNode\"},{\"kind\":4194304,\"name\":\"DropViewNodeParams\",\"url\":\"types/DropViewNodeParams.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"DropViewNode\",\"url\":\"interfaces/DropViewNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/DropViewNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropViewNode\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/DropViewNode.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropViewNode\"},{\"kind\":1024,\"name\":\"ifExists\",\"url\":\"interfaces/DropViewNode.html#ifExists\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropViewNode\"},{\"kind\":1024,\"name\":\"materialized\",\"url\":\"interfaces/DropViewNode.html#materialized\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropViewNode\"},{\"kind\":1024,\"name\":\"cascade\",\"url\":\"interfaces/DropViewNode.html#cascade\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DropViewNode\"},{\"kind\":4194304,\"name\":\"ForeignKeyConstraintNodeProps\",\"url\":\"types/ForeignKeyConstraintNodeProps.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"ForeignKeyConstraintNode\",\"url\":\"interfaces/ForeignKeyConstraintNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ForeignKeyConstraintNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ForeignKeyConstraintNode\"},{\"kind\":1024,\"name\":\"columns\",\"url\":\"interfaces/ForeignKeyConstraintNode.html#columns\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ForeignKeyConstraintNode\"},{\"kind\":1024,\"name\":\"references\",\"url\":\"interfaces/ForeignKeyConstraintNode.html#references\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ForeignKeyConstraintNode\"},{\"kind\":1024,\"name\":\"onDelete\",\"url\":\"interfaces/ForeignKeyConstraintNode.html#onDelete\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ForeignKeyConstraintNode\"},{\"kind\":1024,\"name\":\"onUpdate\",\"url\":\"interfaces/ForeignKeyConstraintNode.html#onUpdate\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ForeignKeyConstraintNode\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/ForeignKeyConstraintNode.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ForeignKeyConstraintNode\"},{\"kind\":256,\"name\":\"FromNode\",\"url\":\"interfaces/FromNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/FromNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"FromNode\"},{\"kind\":1024,\"name\":\"froms\",\"url\":\"interfaces/FromNode.html#froms\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"FromNode\"},{\"kind\":4194304,\"name\":\"GeneratedNodeParams\",\"url\":\"types/GeneratedNodeParams.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"GeneratedNode\",\"url\":\"interfaces/GeneratedNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/GeneratedNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"GeneratedNode\"},{\"kind\":1024,\"name\":\"byDefault\",\"url\":\"interfaces/GeneratedNode.html#byDefault\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"GeneratedNode\"},{\"kind\":1024,\"name\":\"always\",\"url\":\"interfaces/GeneratedNode.html#always\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"GeneratedNode\"},{\"kind\":1024,\"name\":\"identity\",\"url\":\"interfaces/GeneratedNode.html#identity\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"GeneratedNode\"},{\"kind\":1024,\"name\":\"stored\",\"url\":\"interfaces/GeneratedNode.html#stored\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"GeneratedNode\"},{\"kind\":1024,\"name\":\"expression\",\"url\":\"interfaces/GeneratedNode.html#expression\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"GeneratedNode\"},{\"kind\":256,\"name\":\"GroupByItemNode\",\"url\":\"interfaces/GroupByItemNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/GroupByItemNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"GroupByItemNode\"},{\"kind\":1024,\"name\":\"groupBy\",\"url\":\"interfaces/GroupByItemNode.html#groupBy\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"GroupByItemNode\"},{\"kind\":256,\"name\":\"GroupByNode\",\"url\":\"interfaces/GroupByNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/GroupByNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"GroupByNode\"},{\"kind\":1024,\"name\":\"items\",\"url\":\"interfaces/GroupByNode.html#items\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"GroupByNode\"},{\"kind\":256,\"name\":\"HavingNode\",\"url\":\"interfaces/HavingNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/HavingNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"HavingNode\"},{\"kind\":1024,\"name\":\"having\",\"url\":\"interfaces/HavingNode.html#having\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"HavingNode\"},{\"kind\":256,\"name\":\"IdentifierNode\",\"url\":\"interfaces/IdentifierNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/IdentifierNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"IdentifierNode\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/IdentifierNode.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"IdentifierNode\"},{\"kind\":4194304,\"name\":\"InsertQueryNodeProps\",\"url\":\"types/InsertQueryNodeProps.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"InsertQueryNode\",\"url\":\"interfaces/InsertQueryNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/InsertQueryNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryNode\"},{\"kind\":1024,\"name\":\"into\",\"url\":\"interfaces/InsertQueryNode.html#into\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryNode\"},{\"kind\":1024,\"name\":\"columns\",\"url\":\"interfaces/InsertQueryNode.html#columns\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryNode\"},{\"kind\":1024,\"name\":\"values\",\"url\":\"interfaces/InsertQueryNode.html#values\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryNode\"},{\"kind\":1024,\"name\":\"returning\",\"url\":\"interfaces/InsertQueryNode.html#returning\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryNode\"},{\"kind\":1024,\"name\":\"onConflict\",\"url\":\"interfaces/InsertQueryNode.html#onConflict\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryNode\"},{\"kind\":1024,\"name\":\"onDuplicateKey\",\"url\":\"interfaces/InsertQueryNode.html#onDuplicateKey\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryNode\"},{\"kind\":1024,\"name\":\"with\",\"url\":\"interfaces/InsertQueryNode.html#with\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryNode\"},{\"kind\":1024,\"name\":\"ignore\",\"url\":\"interfaces/InsertQueryNode.html#ignore\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryNode\"},{\"kind\":1024,\"name\":\"replace\",\"url\":\"interfaces/InsertQueryNode.html#replace\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryNode\"},{\"kind\":1024,\"name\":\"explain\",\"url\":\"interfaces/InsertQueryNode.html#explain\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"InsertQueryNode\"},{\"kind\":4194304,\"name\":\"JoinType\",\"url\":\"types/JoinType.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"JoinNode\",\"url\":\"interfaces/JoinNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/JoinNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"JoinNode\"},{\"kind\":1024,\"name\":\"joinType\",\"url\":\"interfaces/JoinNode.html#joinType\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"JoinNode\"},{\"kind\":1024,\"name\":\"table\",\"url\":\"interfaces/JoinNode.html#table\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"JoinNode\"},{\"kind\":1024,\"name\":\"on\",\"url\":\"interfaces/JoinNode.html#on\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"JoinNode\"},{\"kind\":256,\"name\":\"LimitNode\",\"url\":\"interfaces/LimitNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/LimitNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"LimitNode\"},{\"kind\":1024,\"name\":\"limit\",\"url\":\"interfaces/LimitNode.html#limit\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"LimitNode\"},{\"kind\":256,\"name\":\"ListNode\",\"url\":\"interfaces/ListNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ListNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ListNode\"},{\"kind\":1024,\"name\":\"items\",\"url\":\"interfaces/ListNode.html#items\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ListNode\"},{\"kind\":256,\"name\":\"ModifyColumnNode\",\"url\":\"interfaces/ModifyColumnNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ModifyColumnNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ModifyColumnNode\"},{\"kind\":1024,\"name\":\"column\",\"url\":\"interfaces/ModifyColumnNode.html#column\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ModifyColumnNode\"},{\"kind\":256,\"name\":\"OffsetNode\",\"url\":\"interfaces/OffsetNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/OffsetNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OffsetNode\"},{\"kind\":1024,\"name\":\"offset\",\"url\":\"interfaces/OffsetNode.html#offset\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OffsetNode\"},{\"kind\":4194304,\"name\":\"OnConflictNodeProps\",\"url\":\"types/OnConflictNodeProps.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"OnConflictNode\",\"url\":\"interfaces/OnConflictNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/OnConflictNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OnConflictNode\"},{\"kind\":1024,\"name\":\"columns\",\"url\":\"interfaces/OnConflictNode.html#columns\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OnConflictNode\"},{\"kind\":1024,\"name\":\"constraint\",\"url\":\"interfaces/OnConflictNode.html#constraint\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OnConflictNode\"},{\"kind\":1024,\"name\":\"indexExpression\",\"url\":\"interfaces/OnConflictNode.html#indexExpression\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OnConflictNode\"},{\"kind\":1024,\"name\":\"indexWhere\",\"url\":\"interfaces/OnConflictNode.html#indexWhere\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OnConflictNode\"},{\"kind\":1024,\"name\":\"updates\",\"url\":\"interfaces/OnConflictNode.html#updates\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OnConflictNode\"},{\"kind\":1024,\"name\":\"updateWhere\",\"url\":\"interfaces/OnConflictNode.html#updateWhere\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OnConflictNode\"},{\"kind\":1024,\"name\":\"doNothing\",\"url\":\"interfaces/OnConflictNode.html#doNothing\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OnConflictNode\"},{\"kind\":4194304,\"name\":\"OnDuplicateKeyNodeProps\",\"url\":\"types/OnDuplicateKeyNodeProps.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"OnDuplicateKeyNode\",\"url\":\"interfaces/OnDuplicateKeyNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/OnDuplicateKeyNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OnDuplicateKeyNode\"},{\"kind\":1024,\"name\":\"updates\",\"url\":\"interfaces/OnDuplicateKeyNode.html#updates\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OnDuplicateKeyNode\"},{\"kind\":256,\"name\":\"OnNode\",\"url\":\"interfaces/OnNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/OnNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OnNode\"},{\"kind\":1024,\"name\":\"on\",\"url\":\"interfaces/OnNode.html#on\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OnNode\"},{\"kind\":64,\"name\":\"isOperationNodeSource\",\"url\":\"functions/isOperationNodeSource.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":256,\"name\":\"OperationNodeSource\",\"url\":\"interfaces/OperationNodeSource.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"toOperationNode\",\"url\":\"interfaces/OperationNodeSource.html#toOperationNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"OperationNodeSource\"},{\"kind\":128,\"name\":\"OperationNodeTransformer\",\"url\":\"classes/OperationNodeTransformer.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/OperationNodeTransformer.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":1024,\"name\":\"nodeStack\",\"url\":\"classes/OperationNodeTransformer.html#nodeStack\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformNode\",\"url\":\"classes/OperationNodeTransformer.html#transformNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformNodeImpl\",\"url\":\"classes/OperationNodeTransformer.html#transformNodeImpl\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformNodeList\",\"url\":\"classes/OperationNodeTransformer.html#transformNodeList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformSelectQuery\",\"url\":\"classes/OperationNodeTransformer.html#transformSelectQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformSelection\",\"url\":\"classes/OperationNodeTransformer.html#transformSelection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformColumn\",\"url\":\"classes/OperationNodeTransformer.html#transformColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformAlias\",\"url\":\"classes/OperationNodeTransformer.html#transformAlias\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformTable\",\"url\":\"classes/OperationNodeTransformer.html#transformTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformFrom\",\"url\":\"classes/OperationNodeTransformer.html#transformFrom\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformReference\",\"url\":\"classes/OperationNodeTransformer.html#transformReference\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformAnd\",\"url\":\"classes/OperationNodeTransformer.html#transformAnd\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformOr\",\"url\":\"classes/OperationNodeTransformer.html#transformOr\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformValueList\",\"url\":\"classes/OperationNodeTransformer.html#transformValueList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformParens\",\"url\":\"classes/OperationNodeTransformer.html#transformParens\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformJoin\",\"url\":\"classes/OperationNodeTransformer.html#transformJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformRaw\",\"url\":\"classes/OperationNodeTransformer.html#transformRaw\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformWhere\",\"url\":\"classes/OperationNodeTransformer.html#transformWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformInsertQuery\",\"url\":\"classes/OperationNodeTransformer.html#transformInsertQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformValues\",\"url\":\"classes/OperationNodeTransformer.html#transformValues\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformDeleteQuery\",\"url\":\"classes/OperationNodeTransformer.html#transformDeleteQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformReturning\",\"url\":\"classes/OperationNodeTransformer.html#transformReturning\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformCreateTable\",\"url\":\"classes/OperationNodeTransformer.html#transformCreateTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformColumnDefinition\",\"url\":\"classes/OperationNodeTransformer.html#transformColumnDefinition\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformAddColumn\",\"url\":\"classes/OperationNodeTransformer.html#transformAddColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformDropTable\",\"url\":\"classes/OperationNodeTransformer.html#transformDropTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformOrderBy\",\"url\":\"classes/OperationNodeTransformer.html#transformOrderBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformOrderByItem\",\"url\":\"classes/OperationNodeTransformer.html#transformOrderByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformGroupBy\",\"url\":\"classes/OperationNodeTransformer.html#transformGroupBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformGroupByItem\",\"url\":\"classes/OperationNodeTransformer.html#transformGroupByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformUpdateQuery\",\"url\":\"classes/OperationNodeTransformer.html#transformUpdateQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformColumnUpdate\",\"url\":\"classes/OperationNodeTransformer.html#transformColumnUpdate\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformLimit\",\"url\":\"classes/OperationNodeTransformer.html#transformLimit\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformOffset\",\"url\":\"classes/OperationNodeTransformer.html#transformOffset\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformOnConflict\",\"url\":\"classes/OperationNodeTransformer.html#transformOnConflict\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformOnDuplicateKey\",\"url\":\"classes/OperationNodeTransformer.html#transformOnDuplicateKey\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformCreateIndex\",\"url\":\"classes/OperationNodeTransformer.html#transformCreateIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformList\",\"url\":\"classes/OperationNodeTransformer.html#transformList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformDropIndex\",\"url\":\"classes/OperationNodeTransformer.html#transformDropIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformPrimaryKeyConstraint\",\"url\":\"classes/OperationNodeTransformer.html#transformPrimaryKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformUniqueConstraint\",\"url\":\"classes/OperationNodeTransformer.html#transformUniqueConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformForeignKeyConstraint\",\"url\":\"classes/OperationNodeTransformer.html#transformForeignKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformSetOperation\",\"url\":\"classes/OperationNodeTransformer.html#transformSetOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformReferences\",\"url\":\"classes/OperationNodeTransformer.html#transformReferences\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformCheckConstraint\",\"url\":\"classes/OperationNodeTransformer.html#transformCheckConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformWith\",\"url\":\"classes/OperationNodeTransformer.html#transformWith\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformCommonTableExpression\",\"url\":\"classes/OperationNodeTransformer.html#transformCommonTableExpression\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformCommonTableExpressionName\",\"url\":\"classes/OperationNodeTransformer.html#transformCommonTableExpressionName\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformHaving\",\"url\":\"classes/OperationNodeTransformer.html#transformHaving\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformCreateSchema\",\"url\":\"classes/OperationNodeTransformer.html#transformCreateSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformDropSchema\",\"url\":\"classes/OperationNodeTransformer.html#transformDropSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformAlterTable\",\"url\":\"classes/OperationNodeTransformer.html#transformAlterTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformDropColumn\",\"url\":\"classes/OperationNodeTransformer.html#transformDropColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformRenameColumn\",\"url\":\"classes/OperationNodeTransformer.html#transformRenameColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformAlterColumn\",\"url\":\"classes/OperationNodeTransformer.html#transformAlterColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformModifyColumn\",\"url\":\"classes/OperationNodeTransformer.html#transformModifyColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformAddConstraint\",\"url\":\"classes/OperationNodeTransformer.html#transformAddConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformDropConstraint\",\"url\":\"classes/OperationNodeTransformer.html#transformDropConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformCreateView\",\"url\":\"classes/OperationNodeTransformer.html#transformCreateView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformDropView\",\"url\":\"classes/OperationNodeTransformer.html#transformDropView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformGenerated\",\"url\":\"classes/OperationNodeTransformer.html#transformGenerated\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformDefaultValue\",\"url\":\"classes/OperationNodeTransformer.html#transformDefaultValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformOn\",\"url\":\"classes/OperationNodeTransformer.html#transformOn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformSelectModifier\",\"url\":\"classes/OperationNodeTransformer.html#transformSelectModifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformCreateType\",\"url\":\"classes/OperationNodeTransformer.html#transformCreateType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformDropType\",\"url\":\"classes/OperationNodeTransformer.html#transformDropType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformExplain\",\"url\":\"classes/OperationNodeTransformer.html#transformExplain\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformSchemableIdentifier\",\"url\":\"classes/OperationNodeTransformer.html#transformSchemableIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformAggregateFunction\",\"url\":\"classes/OperationNodeTransformer.html#transformAggregateFunction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformOver\",\"url\":\"classes/OperationNodeTransformer.html#transformOver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformPartitionBy\",\"url\":\"classes/OperationNodeTransformer.html#transformPartitionBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformPartitionByItem\",\"url\":\"classes/OperationNodeTransformer.html#transformPartitionByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformBinaryOperation\",\"url\":\"classes/OperationNodeTransformer.html#transformBinaryOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformUnaryOperation\",\"url\":\"classes/OperationNodeTransformer.html#transformUnaryOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformUsing\",\"url\":\"classes/OperationNodeTransformer.html#transformUsing\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformFunction\",\"url\":\"classes/OperationNodeTransformer.html#transformFunction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformCase\",\"url\":\"classes/OperationNodeTransformer.html#transformCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformWhen\",\"url\":\"classes/OperationNodeTransformer.html#transformWhen\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformDataType\",\"url\":\"classes/OperationNodeTransformer.html#transformDataType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformSelectAll\",\"url\":\"classes/OperationNodeTransformer.html#transformSelectAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformIdentifier\",\"url\":\"classes/OperationNodeTransformer.html#transformIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformValue\",\"url\":\"classes/OperationNodeTransformer.html#transformValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformPrimitiveValueList\",\"url\":\"classes/OperationNodeTransformer.html#transformPrimitiveValueList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformOperator\",\"url\":\"classes/OperationNodeTransformer.html#transformOperator\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":2048,\"name\":\"transformDefaultInsertValue\",\"url\":\"classes/OperationNodeTransformer.html#transformDefaultInsertValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeTransformer\"},{\"kind\":128,\"name\":\"OperationNodeVisitor\",\"url\":\"classes/OperationNodeVisitor.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/OperationNodeVisitor.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":1024,\"name\":\"nodeStack\",\"url\":\"classes/OperationNodeVisitor.html#nodeStack\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":262144,\"name\":\"parentNode\",\"url\":\"classes/OperationNodeVisitor.html#parentNode\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitNode\",\"url\":\"classes/OperationNodeVisitor.html#visitNode\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitSelectQuery\",\"url\":\"classes/OperationNodeVisitor.html#visitSelectQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitSelection\",\"url\":\"classes/OperationNodeVisitor.html#visitSelection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitColumn\",\"url\":\"classes/OperationNodeVisitor.html#visitColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitAlias\",\"url\":\"classes/OperationNodeVisitor.html#visitAlias\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitTable\",\"url\":\"classes/OperationNodeVisitor.html#visitTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitFrom\",\"url\":\"classes/OperationNodeVisitor.html#visitFrom\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitReference\",\"url\":\"classes/OperationNodeVisitor.html#visitReference\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitAnd\",\"url\":\"classes/OperationNodeVisitor.html#visitAnd\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitOr\",\"url\":\"classes/OperationNodeVisitor.html#visitOr\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitValueList\",\"url\":\"classes/OperationNodeVisitor.html#visitValueList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitParens\",\"url\":\"classes/OperationNodeVisitor.html#visitParens\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitJoin\",\"url\":\"classes/OperationNodeVisitor.html#visitJoin\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitRaw\",\"url\":\"classes/OperationNodeVisitor.html#visitRaw\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitWhere\",\"url\":\"classes/OperationNodeVisitor.html#visitWhere\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitInsertQuery\",\"url\":\"classes/OperationNodeVisitor.html#visitInsertQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitDeleteQuery\",\"url\":\"classes/OperationNodeVisitor.html#visitDeleteQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitReturning\",\"url\":\"classes/OperationNodeVisitor.html#visitReturning\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitCreateTable\",\"url\":\"classes/OperationNodeVisitor.html#visitCreateTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitAddColumn\",\"url\":\"classes/OperationNodeVisitor.html#visitAddColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitColumnDefinition\",\"url\":\"classes/OperationNodeVisitor.html#visitColumnDefinition\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitDropTable\",\"url\":\"classes/OperationNodeVisitor.html#visitDropTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitOrderBy\",\"url\":\"classes/OperationNodeVisitor.html#visitOrderBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitOrderByItem\",\"url\":\"classes/OperationNodeVisitor.html#visitOrderByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitGroupBy\",\"url\":\"classes/OperationNodeVisitor.html#visitGroupBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitGroupByItem\",\"url\":\"classes/OperationNodeVisitor.html#visitGroupByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitUpdateQuery\",\"url\":\"classes/OperationNodeVisitor.html#visitUpdateQuery\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitColumnUpdate\",\"url\":\"classes/OperationNodeVisitor.html#visitColumnUpdate\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitLimit\",\"url\":\"classes/OperationNodeVisitor.html#visitLimit\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitOffset\",\"url\":\"classes/OperationNodeVisitor.html#visitOffset\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitOnConflict\",\"url\":\"classes/OperationNodeVisitor.html#visitOnConflict\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitOnDuplicateKey\",\"url\":\"classes/OperationNodeVisitor.html#visitOnDuplicateKey\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitCreateIndex\",\"url\":\"classes/OperationNodeVisitor.html#visitCreateIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitDropIndex\",\"url\":\"classes/OperationNodeVisitor.html#visitDropIndex\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitList\",\"url\":\"classes/OperationNodeVisitor.html#visitList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitPrimaryKeyConstraint\",\"url\":\"classes/OperationNodeVisitor.html#visitPrimaryKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitUniqueConstraint\",\"url\":\"classes/OperationNodeVisitor.html#visitUniqueConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitReferences\",\"url\":\"classes/OperationNodeVisitor.html#visitReferences\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitCheckConstraint\",\"url\":\"classes/OperationNodeVisitor.html#visitCheckConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitWith\",\"url\":\"classes/OperationNodeVisitor.html#visitWith\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitCommonTableExpression\",\"url\":\"classes/OperationNodeVisitor.html#visitCommonTableExpression\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitCommonTableExpressionName\",\"url\":\"classes/OperationNodeVisitor.html#visitCommonTableExpressionName\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitHaving\",\"url\":\"classes/OperationNodeVisitor.html#visitHaving\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitCreateSchema\",\"url\":\"classes/OperationNodeVisitor.html#visitCreateSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitDropSchema\",\"url\":\"classes/OperationNodeVisitor.html#visitDropSchema\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitAlterTable\",\"url\":\"classes/OperationNodeVisitor.html#visitAlterTable\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitDropColumn\",\"url\":\"classes/OperationNodeVisitor.html#visitDropColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitRenameColumn\",\"url\":\"classes/OperationNodeVisitor.html#visitRenameColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitAlterColumn\",\"url\":\"classes/OperationNodeVisitor.html#visitAlterColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitModifyColumn\",\"url\":\"classes/OperationNodeVisitor.html#visitModifyColumn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitAddConstraint\",\"url\":\"classes/OperationNodeVisitor.html#visitAddConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitDropConstraint\",\"url\":\"classes/OperationNodeVisitor.html#visitDropConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitForeignKeyConstraint\",\"url\":\"classes/OperationNodeVisitor.html#visitForeignKeyConstraint\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitDataType\",\"url\":\"classes/OperationNodeVisitor.html#visitDataType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitSelectAll\",\"url\":\"classes/OperationNodeVisitor.html#visitSelectAll\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitIdentifier\",\"url\":\"classes/OperationNodeVisitor.html#visitIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitSchemableIdentifier\",\"url\":\"classes/OperationNodeVisitor.html#visitSchemableIdentifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitValue\",\"url\":\"classes/OperationNodeVisitor.html#visitValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitPrimitiveValueList\",\"url\":\"classes/OperationNodeVisitor.html#visitPrimitiveValueList\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitOperator\",\"url\":\"classes/OperationNodeVisitor.html#visitOperator\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitCreateView\",\"url\":\"classes/OperationNodeVisitor.html#visitCreateView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitDropView\",\"url\":\"classes/OperationNodeVisitor.html#visitDropView\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitGenerated\",\"url\":\"classes/OperationNodeVisitor.html#visitGenerated\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitDefaultValue\",\"url\":\"classes/OperationNodeVisitor.html#visitDefaultValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitOn\",\"url\":\"classes/OperationNodeVisitor.html#visitOn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitValues\",\"url\":\"classes/OperationNodeVisitor.html#visitValues\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitSelectModifier\",\"url\":\"classes/OperationNodeVisitor.html#visitSelectModifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitCreateType\",\"url\":\"classes/OperationNodeVisitor.html#visitCreateType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitDropType\",\"url\":\"classes/OperationNodeVisitor.html#visitDropType\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitExplain\",\"url\":\"classes/OperationNodeVisitor.html#visitExplain\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitDefaultInsertValue\",\"url\":\"classes/OperationNodeVisitor.html#visitDefaultInsertValue\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitAggregateFunction\",\"url\":\"classes/OperationNodeVisitor.html#visitAggregateFunction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitOver\",\"url\":\"classes/OperationNodeVisitor.html#visitOver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitPartitionBy\",\"url\":\"classes/OperationNodeVisitor.html#visitPartitionBy\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitPartitionByItem\",\"url\":\"classes/OperationNodeVisitor.html#visitPartitionByItem\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitSetOperation\",\"url\":\"classes/OperationNodeVisitor.html#visitSetOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitBinaryOperation\",\"url\":\"classes/OperationNodeVisitor.html#visitBinaryOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitUnaryOperation\",\"url\":\"classes/OperationNodeVisitor.html#visitUnaryOperation\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitUsing\",\"url\":\"classes/OperationNodeVisitor.html#visitUsing\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitFunction\",\"url\":\"classes/OperationNodeVisitor.html#visitFunction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitCase\",\"url\":\"classes/OperationNodeVisitor.html#visitCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":2048,\"name\":\"visitWhen\",\"url\":\"classes/OperationNodeVisitor.html#visitWhen\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"OperationNodeVisitor\"},{\"kind\":4194304,\"name\":\"OperationNodeKind\",\"url\":\"types/OperationNodeKind.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"OperationNode\",\"url\":\"interfaces/OperationNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/OperationNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OperationNode\"},{\"kind\":64,\"name\":\"isOperator\",\"url\":\"functions/isOperator.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":64,\"name\":\"isBinaryOperator\",\"url\":\"functions/isBinaryOperator.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":64,\"name\":\"isComparisonOperator\",\"url\":\"functions/isComparisonOperator.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":64,\"name\":\"isArithmeticOperator\",\"url\":\"functions/isArithmeticOperator.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":32,\"name\":\"COMPARISON_OPERATORS\",\"url\":\"variables/COMPARISON_OPERATORS.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":32,\"name\":\"ARITHMETIC_OPERATORS\",\"url\":\"variables/ARITHMETIC_OPERATORS.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":32,\"name\":\"BINARY_OPERATORS\",\"url\":\"variables/BINARY_OPERATORS.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":32,\"name\":\"UNARY_FILTER_OPERATORS\",\"url\":\"variables/UNARY_FILTER_OPERATORS.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":32,\"name\":\"UNARY_OPERATORS\",\"url\":\"variables/UNARY_OPERATORS.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":32,\"name\":\"OPERATORS\",\"url\":\"variables/OPERATORS.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":4194304,\"name\":\"ComparisonOperator\",\"url\":\"types/ComparisonOperator.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"ArithmeticOperator\",\"url\":\"types/ArithmeticOperator.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"BinaryOperator\",\"url\":\"types/BinaryOperator.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"UnaryOperator\",\"url\":\"types/UnaryOperator.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"UnaryFilterOperator\",\"url\":\"types/UnaryFilterOperator.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"Operator\",\"url\":\"types/Operator.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"OperatorNode\",\"url\":\"interfaces/OperatorNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/OperatorNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OperatorNode\"},{\"kind\":1024,\"name\":\"operator\",\"url\":\"interfaces/OperatorNode.html#operator\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OperatorNode\"},{\"kind\":256,\"name\":\"OrNode\",\"url\":\"interfaces/OrNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/OrNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OrNode\"},{\"kind\":1024,\"name\":\"left\",\"url\":\"interfaces/OrNode.html#left\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OrNode\"},{\"kind\":1024,\"name\":\"right\",\"url\":\"interfaces/OrNode.html#right\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OrNode\"},{\"kind\":256,\"name\":\"OrderByItemNode\",\"url\":\"interfaces/OrderByItemNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/OrderByItemNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OrderByItemNode\"},{\"kind\":1024,\"name\":\"orderBy\",\"url\":\"interfaces/OrderByItemNode.html#orderBy\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OrderByItemNode\"},{\"kind\":1024,\"name\":\"direction\",\"url\":\"interfaces/OrderByItemNode.html#direction\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OrderByItemNode\"},{\"kind\":256,\"name\":\"OrderByNode\",\"url\":\"interfaces/OrderByNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/OrderByNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OrderByNode\"},{\"kind\":1024,\"name\":\"items\",\"url\":\"interfaces/OrderByNode.html#items\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OrderByNode\"},{\"kind\":256,\"name\":\"ParensNode\",\"url\":\"interfaces/ParensNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ParensNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ParensNode\"},{\"kind\":1024,\"name\":\"node\",\"url\":\"interfaces/ParensNode.html#node\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ParensNode\"},{\"kind\":256,\"name\":\"PrimaryKeyConstraintNode\",\"url\":\"interfaces/PrimaryKeyConstraintNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/PrimaryKeyConstraintNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PrimaryKeyConstraintNode\"},{\"kind\":1024,\"name\":\"columns\",\"url\":\"interfaces/PrimaryKeyConstraintNode.html#columns\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PrimaryKeyConstraintNode\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/PrimaryKeyConstraintNode.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PrimaryKeyConstraintNode\"},{\"kind\":256,\"name\":\"PrimitiveValueListNode\",\"url\":\"interfaces/PrimitiveValueListNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/PrimitiveValueListNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PrimitiveValueListNode\"},{\"kind\":1024,\"name\":\"values\",\"url\":\"interfaces/PrimitiveValueListNode.html#values\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PrimitiveValueListNode\"},{\"kind\":4194304,\"name\":\"QueryNode\",\"url\":\"types/QueryNode.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"RawNode\",\"url\":\"interfaces/RawNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/RawNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"RawNode\"},{\"kind\":1024,\"name\":\"sqlFragments\",\"url\":\"interfaces/RawNode.html#sqlFragments\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"RawNode\"},{\"kind\":1024,\"name\":\"parameters\",\"url\":\"interfaces/RawNode.html#parameters\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"RawNode\"},{\"kind\":256,\"name\":\"ReferenceNode\",\"url\":\"interfaces/ReferenceNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ReferenceNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ReferenceNode\"},{\"kind\":1024,\"name\":\"table\",\"url\":\"interfaces/ReferenceNode.html#table\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ReferenceNode\"},{\"kind\":1024,\"name\":\"column\",\"url\":\"interfaces/ReferenceNode.html#column\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ReferenceNode\"},{\"kind\":32,\"name\":\"ON_MODIFY_FOREIGN_ACTIONS\",\"url\":\"variables/ON_MODIFY_FOREIGN_ACTIONS.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":4194304,\"name\":\"OnModifyForeignAction\",\"url\":\"types/OnModifyForeignAction.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"ReferencesNode\",\"url\":\"interfaces/ReferencesNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ReferencesNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ReferencesNode\"},{\"kind\":1024,\"name\":\"table\",\"url\":\"interfaces/ReferencesNode.html#table\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ReferencesNode\"},{\"kind\":1024,\"name\":\"columns\",\"url\":\"interfaces/ReferencesNode.html#columns\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ReferencesNode\"},{\"kind\":1024,\"name\":\"onDelete\",\"url\":\"interfaces/ReferencesNode.html#onDelete\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ReferencesNode\"},{\"kind\":1024,\"name\":\"onUpdate\",\"url\":\"interfaces/ReferencesNode.html#onUpdate\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ReferencesNode\"},{\"kind\":256,\"name\":\"RenameColumnNode\",\"url\":\"interfaces/RenameColumnNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/RenameColumnNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"RenameColumnNode\"},{\"kind\":1024,\"name\":\"column\",\"url\":\"interfaces/RenameColumnNode.html#column\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"RenameColumnNode\"},{\"kind\":1024,\"name\":\"renameTo\",\"url\":\"interfaces/RenameColumnNode.html#renameTo\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"RenameColumnNode\"},{\"kind\":256,\"name\":\"ReturningNode\",\"url\":\"interfaces/ReturningNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ReturningNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ReturningNode\"},{\"kind\":1024,\"name\":\"selections\",\"url\":\"interfaces/ReturningNode.html#selections\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ReturningNode\"},{\"kind\":256,\"name\":\"SelectAllNode\",\"url\":\"interfaces/SelectAllNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/SelectAllNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectAllNode\"},{\"kind\":256,\"name\":\"SelectQueryNode\",\"url\":\"interfaces/SelectQueryNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/SelectQueryNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"from\",\"url\":\"interfaces/SelectQueryNode.html#from\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"selections\",\"url\":\"interfaces/SelectQueryNode.html#selections\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"distinctOn\",\"url\":\"interfaces/SelectQueryNode.html#distinctOn\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"joins\",\"url\":\"interfaces/SelectQueryNode.html#joins\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"groupBy\",\"url\":\"interfaces/SelectQueryNode.html#groupBy\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"orderBy\",\"url\":\"interfaces/SelectQueryNode.html#orderBy\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"where\",\"url\":\"interfaces/SelectQueryNode.html#where\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"frontModifiers\",\"url\":\"interfaces/SelectQueryNode.html#frontModifiers\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"endModifiers\",\"url\":\"interfaces/SelectQueryNode.html#endModifiers\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"limit\",\"url\":\"interfaces/SelectQueryNode.html#limit\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"offset\",\"url\":\"interfaces/SelectQueryNode.html#offset\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"with\",\"url\":\"interfaces/SelectQueryNode.html#with\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"having\",\"url\":\"interfaces/SelectQueryNode.html#having\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"explain\",\"url\":\"interfaces/SelectQueryNode.html#explain\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":1024,\"name\":\"setOperations\",\"url\":\"interfaces/SelectQueryNode.html#setOperations\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectQueryNode\"},{\"kind\":256,\"name\":\"SelectionNode\",\"url\":\"interfaces/SelectionNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/SelectionNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectionNode\"},{\"kind\":1024,\"name\":\"selection\",\"url\":\"interfaces/SelectionNode.html#selection\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SelectionNode\"},{\"kind\":256,\"name\":\"TableNode\",\"url\":\"interfaces/TableNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/TableNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"TableNode\"},{\"kind\":1024,\"name\":\"table\",\"url\":\"interfaces/TableNode.html#table\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"TableNode\"},{\"kind\":256,\"name\":\"UniqueConstraintNode\",\"url\":\"interfaces/UniqueConstraintNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/UniqueConstraintNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UniqueConstraintNode\"},{\"kind\":1024,\"name\":\"columns\",\"url\":\"interfaces/UniqueConstraintNode.html#columns\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UniqueConstraintNode\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/UniqueConstraintNode.html#name\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UniqueConstraintNode\"},{\"kind\":4194304,\"name\":\"UpdateValuesNode\",\"url\":\"types/UpdateValuesNode.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"UpdateQueryNode\",\"url\":\"interfaces/UpdateQueryNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/UpdateQueryNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UpdateQueryNode\"},{\"kind\":1024,\"name\":\"table\",\"url\":\"interfaces/UpdateQueryNode.html#table\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UpdateQueryNode\"},{\"kind\":1024,\"name\":\"from\",\"url\":\"interfaces/UpdateQueryNode.html#from\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UpdateQueryNode\"},{\"kind\":1024,\"name\":\"joins\",\"url\":\"interfaces/UpdateQueryNode.html#joins\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UpdateQueryNode\"},{\"kind\":1024,\"name\":\"where\",\"url\":\"interfaces/UpdateQueryNode.html#where\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UpdateQueryNode\"},{\"kind\":1024,\"name\":\"updates\",\"url\":\"interfaces/UpdateQueryNode.html#updates\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UpdateQueryNode\"},{\"kind\":1024,\"name\":\"returning\",\"url\":\"interfaces/UpdateQueryNode.html#returning\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UpdateQueryNode\"},{\"kind\":1024,\"name\":\"with\",\"url\":\"interfaces/UpdateQueryNode.html#with\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UpdateQueryNode\"},{\"kind\":1024,\"name\":\"explain\",\"url\":\"interfaces/UpdateQueryNode.html#explain\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UpdateQueryNode\"},{\"kind\":256,\"name\":\"ValueListNode\",\"url\":\"interfaces/ValueListNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ValueListNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ValueListNode\"},{\"kind\":1024,\"name\":\"values\",\"url\":\"interfaces/ValueListNode.html#values\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ValueListNode\"},{\"kind\":256,\"name\":\"ValueNode\",\"url\":\"interfaces/ValueNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ValueNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ValueNode\"},{\"kind\":1024,\"name\":\"value\",\"url\":\"interfaces/ValueNode.html#value\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ValueNode\"},{\"kind\":1024,\"name\":\"immediate\",\"url\":\"interfaces/ValueNode.html#immediate\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ValueNode\"},{\"kind\":4194304,\"name\":\"ValuesItemNode\",\"url\":\"types/ValuesItemNode.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"ValuesNode\",\"url\":\"interfaces/ValuesNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ValuesNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ValuesNode\"},{\"kind\":1024,\"name\":\"values\",\"url\":\"interfaces/ValuesNode.html#values\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ValuesNode\"},{\"kind\":256,\"name\":\"WhenNode\",\"url\":\"interfaces/WhenNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/WhenNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"WhenNode\"},{\"kind\":1024,\"name\":\"condition\",\"url\":\"interfaces/WhenNode.html#condition\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"WhenNode\"},{\"kind\":1024,\"name\":\"result\",\"url\":\"interfaces/WhenNode.html#result\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"WhenNode\"},{\"kind\":256,\"name\":\"WhereNode\",\"url\":\"interfaces/WhereNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/WhereNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"WhereNode\"},{\"kind\":1024,\"name\":\"where\",\"url\":\"interfaces/WhereNode.html#where\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"WhereNode\"},{\"kind\":4194304,\"name\":\"WithNodeParams\",\"url\":\"types/WithNodeParams.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"WithNode\",\"url\":\"interfaces/WithNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/WithNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"WithNode\"},{\"kind\":1024,\"name\":\"expressions\",\"url\":\"interfaces/WithNode.html#expressions\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"WithNode\"},{\"kind\":1024,\"name\":\"recursive\",\"url\":\"interfaces/WithNode.html#recursive\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"WithNode\"},{\"kind\":256,\"name\":\"ExplainNode\",\"url\":\"interfaces/ExplainNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/ExplainNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ExplainNode\"},{\"kind\":1024,\"name\":\"format\",\"url\":\"interfaces/ExplainNode.html#format\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ExplainNode\"},{\"kind\":1024,\"name\":\"options\",\"url\":\"interfaces/ExplainNode.html#options\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ExplainNode\"},{\"kind\":256,\"name\":\"DefaultInsertValueNode\",\"url\":\"interfaces/DefaultInsertValueNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/DefaultInsertValueNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"DefaultInsertValueNode\"},{\"kind\":256,\"name\":\"AggregateFunctionNode\",\"url\":\"interfaces/AggregateFunctionNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/AggregateFunctionNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AggregateFunctionNode\"},{\"kind\":1024,\"name\":\"func\",\"url\":\"interfaces/AggregateFunctionNode.html#func\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AggregateFunctionNode\"},{\"kind\":1024,\"name\":\"aggregated\",\"url\":\"interfaces/AggregateFunctionNode.html#aggregated\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AggregateFunctionNode\"},{\"kind\":1024,\"name\":\"distinct\",\"url\":\"interfaces/AggregateFunctionNode.html#distinct\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AggregateFunctionNode\"},{\"kind\":1024,\"name\":\"filter\",\"url\":\"interfaces/AggregateFunctionNode.html#filter\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AggregateFunctionNode\"},{\"kind\":1024,\"name\":\"over\",\"url\":\"interfaces/AggregateFunctionNode.html#over\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"AggregateFunctionNode\"},{\"kind\":256,\"name\":\"OverNode\",\"url\":\"interfaces/OverNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/OverNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OverNode\"},{\"kind\":1024,\"name\":\"orderBy\",\"url\":\"interfaces/OverNode.html#orderBy\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OverNode\"},{\"kind\":1024,\"name\":\"partitionBy\",\"url\":\"interfaces/OverNode.html#partitionBy\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"OverNode\"},{\"kind\":256,\"name\":\"PartitionByNode\",\"url\":\"interfaces/PartitionByNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/PartitionByNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PartitionByNode\"},{\"kind\":1024,\"name\":\"items\",\"url\":\"interfaces/PartitionByNode.html#items\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PartitionByNode\"},{\"kind\":256,\"name\":\"PartitionByItemNode\",\"url\":\"interfaces/PartitionByItemNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/PartitionByItemNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PartitionByItemNode\"},{\"kind\":1024,\"name\":\"partitionBy\",\"url\":\"interfaces/PartitionByItemNode.html#partitionBy\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"PartitionByItemNode\"},{\"kind\":4194304,\"name\":\"SetOperator\",\"url\":\"types/SetOperator.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"SetOperationNode\",\"url\":\"interfaces/SetOperationNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/SetOperationNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SetOperationNode\"},{\"kind\":1024,\"name\":\"operator\",\"url\":\"interfaces/SetOperationNode.html#operator\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SetOperationNode\"},{\"kind\":1024,\"name\":\"expression\",\"url\":\"interfaces/SetOperationNode.html#expression\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SetOperationNode\"},{\"kind\":1024,\"name\":\"all\",\"url\":\"interfaces/SetOperationNode.html#all\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"SetOperationNode\"},{\"kind\":256,\"name\":\"BinaryOperationNode\",\"url\":\"interfaces/BinaryOperationNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/BinaryOperationNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"BinaryOperationNode\"},{\"kind\":1024,\"name\":\"leftOperand\",\"url\":\"interfaces/BinaryOperationNode.html#leftOperand\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"BinaryOperationNode\"},{\"kind\":1024,\"name\":\"operator\",\"url\":\"interfaces/BinaryOperationNode.html#operator\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"BinaryOperationNode\"},{\"kind\":1024,\"name\":\"rightOperand\",\"url\":\"interfaces/BinaryOperationNode.html#rightOperand\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"BinaryOperationNode\"},{\"kind\":256,\"name\":\"UnaryOperationNode\",\"url\":\"interfaces/UnaryOperationNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/UnaryOperationNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UnaryOperationNode\"},{\"kind\":1024,\"name\":\"operator\",\"url\":\"interfaces/UnaryOperationNode.html#operator\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UnaryOperationNode\"},{\"kind\":1024,\"name\":\"operand\",\"url\":\"interfaces/UnaryOperationNode.html#operand\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UnaryOperationNode\"},{\"kind\":256,\"name\":\"UsingNode\",\"url\":\"interfaces/UsingNode.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"kind\",\"url\":\"interfaces/UsingNode.html#kind\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UsingNode\"},{\"kind\":1024,\"name\":\"tables\",\"url\":\"interfaces/UsingNode.html#tables\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"UsingNode\"},{\"kind\":4194304,\"name\":\"ColumnType\",\"url\":\"types/ColumnType.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/ColumnType.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"ColumnType\"},{\"kind\":1024,\"name\":\"__select__\",\"url\":\"types/ColumnType.html#__type.__select__\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"ColumnType.__type\"},{\"kind\":1024,\"name\":\"__insert__\",\"url\":\"types/ColumnType.html#__type.__insert__\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"ColumnType.__type\"},{\"kind\":1024,\"name\":\"__update__\",\"url\":\"types/ColumnType.html#__type.__update__\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"ColumnType.__type\"},{\"kind\":4194304,\"name\":\"Generated\",\"url\":\"types/Generated.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"GeneratedAlways\",\"url\":\"types/GeneratedAlways.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"SelectType\",\"url\":\"types/SelectType.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"InsertType\",\"url\":\"types/InsertType.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"UpdateType\",\"url\":\"types/UpdateType.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"NullableInsertKeys\",\"url\":\"types/NullableInsertKeys.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"NonNullableInsertKeys\",\"url\":\"types/NonNullableInsertKeys.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"UpdateKeys\",\"url\":\"types/UpdateKeys.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"Selectable\",\"url\":\"types/Selectable.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"Insertable\",\"url\":\"types/Insertable.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"Updateable\",\"url\":\"types/Updateable.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":64,\"name\":\"isCompilable\",\"url\":\"functions/isCompilable.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":256,\"name\":\"Compilable\",\"url\":\"interfaces/Compilable.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"compile\",\"url\":\"interfaces/Compilable.html#compile\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Compilable\"},{\"kind\":4194304,\"name\":\"ExplainFormat\",\"url\":\"types/ExplainFormat.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"Explainable\",\"url\":\"interfaces/Explainable.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"explain\",\"url\":\"interfaces/Explainable.html#explain\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Explainable\"},{\"kind\":256,\"name\":\"Streamable\",\"url\":\"interfaces/Streamable.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":2048,\"name\":\"stream\",\"url\":\"interfaces/Streamable.html#stream\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"Streamable\"},{\"kind\":32,\"name\":\"LOG_LEVELS\",\"url\":\"variables/LOG_LEVELS.html\",\"classes\":\"tsd-kind-variable\"},{\"kind\":4194304,\"name\":\"LogLevel\",\"url\":\"types/LogLevel.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":256,\"name\":\"QueryLogEvent\",\"url\":\"interfaces/QueryLogEvent.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"level\",\"url\":\"interfaces/QueryLogEvent.html#level\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"QueryLogEvent\"},{\"kind\":1024,\"name\":\"query\",\"url\":\"interfaces/QueryLogEvent.html#query\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"QueryLogEvent\"},{\"kind\":1024,\"name\":\"queryDurationMillis\",\"url\":\"interfaces/QueryLogEvent.html#queryDurationMillis\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"QueryLogEvent\"},{\"kind\":256,\"name\":\"ErrorLogEvent\",\"url\":\"interfaces/ErrorLogEvent.html\",\"classes\":\"tsd-kind-interface\"},{\"kind\":1024,\"name\":\"level\",\"url\":\"interfaces/ErrorLogEvent.html#level\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ErrorLogEvent\"},{\"kind\":1024,\"name\":\"error\",\"url\":\"interfaces/ErrorLogEvent.html#error\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ErrorLogEvent\"},{\"kind\":1024,\"name\":\"query\",\"url\":\"interfaces/ErrorLogEvent.html#query\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ErrorLogEvent\"},{\"kind\":1024,\"name\":\"queryDurationMillis\",\"url\":\"interfaces/ErrorLogEvent.html#queryDurationMillis\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"ErrorLogEvent\"},{\"kind\":4194304,\"name\":\"LogEvent\",\"url\":\"types/LogEvent.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":4194304,\"name\":\"Logger\",\"url\":\"types/Logger.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/Logger.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"Logger\"},{\"kind\":4194304,\"name\":\"LogConfig\",\"url\":\"types/LogConfig.html\",\"classes\":\"tsd-kind-type-alias\"},{\"kind\":128,\"name\":\"Log\",\"url\":\"classes/Log.html\",\"classes\":\"tsd-kind-class\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/Log.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"Log\"},{\"kind\":2048,\"name\":\"isLevelEnabled\",\"url\":\"classes/Log.html#isLevelEnabled\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Log\"},{\"kind\":2048,\"name\":\"query\",\"url\":\"classes/Log.html#query\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Log\"},{\"kind\":2048,\"name\":\"error\",\"url\":\"classes/Log.html#error\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"Log\"},{\"kind\":4194304,\"name\":\"InferResult\",\"url\":\"types/InferResult.html\",\"classes\":\"tsd-kind-type-alias\"}],\"index\":{\"version\":\"2.3.9\",\"fields\":[\"name\",\"comment\"],\"fieldVectors\":[[\"name/0\",[0,67.731]],[\"comment/0\",[]],[\"name/1\",[1,64.366]],[\"comment/1\",[]],[\"name/2\",[2,61.853]],[\"comment/2\",[]],[\"name/3\",[3,64.366]],[\"comment/3\",[]],[\"name/4\",[4,64.366]],[\"comment/4\",[]],[\"name/5\",[5,67.731]],[\"comment/5\",[]],[\"name/6\",[6,72.839]],[\"comment/6\",[]],[\"name/7\",[7,72.839]],[\"comment/7\",[]],[\"name/8\",[8,72.839]],[\"comment/8\",[]],[\"name/9\",[9,72.839]],[\"comment/9\",[]],[\"name/10\",[10,72.839]],[\"comment/10\",[]],[\"name/11\",[11,72.839]],[\"comment/11\",[]],[\"name/12\",[12,72.839]],[\"comment/12\",[]],[\"name/13\",[13,72.839]],[\"comment/13\",[]],[\"name/14\",[14,59.846]],[\"comment/14\",[]],[\"name/15\",[0,67.731]],[\"comment/15\",[]],[\"name/16\",[15,72.839]],[\"comment/16\",[]],[\"name/17\",[16,72.839]],[\"comment/17\",[]],[\"name/18\",[17,72.839]],[\"comment/18\",[]],[\"name/19\",[18,72.839]],[\"comment/19\",[]],[\"name/20\",[19,72.839]],[\"comment/20\",[]],[\"name/21\",[20,72.839]],[\"comment/21\",[]],[\"name/22\",[21,72.839]],[\"comment/22\",[]],[\"name/23\",[22,72.839]],[\"comment/23\",[]],[\"name/24\",[23,72.839]],[\"comment/24\",[]],[\"name/25\",[24,72.839]],[\"comment/25\",[]],[\"name/26\",[25,72.839]],[\"comment/26\",[]],[\"name/27\",[26,72.839]],[\"comment/27\",[]],[\"name/28\",[27,67.731]],[\"comment/28\",[]],[\"name/29\",[28,72.839]],[\"comment/29\",[]],[\"name/30\",[29,72.839]],[\"comment/30\",[]],[\"name/31\",[30,72.839]],[\"comment/31\",[]],[\"name/32\",[31,72.839]],[\"comment/32\",[]],[\"name/33\",[32,72.839]],[\"comment/33\",[]],[\"name/34\",[33,72.839]],[\"comment/34\",[]],[\"name/35\",[34,72.839]],[\"comment/35\",[]],[\"name/36\",[35,72.839]],[\"comment/36\",[]],[\"name/37\",[36,72.839]],[\"comment/37\",[]],[\"name/38\",[37,72.839]],[\"comment/38\",[]],[\"name/39\",[38,72.839]],[\"comment/39\",[]],[\"name/40\",[39,72.839]],[\"comment/40\",[]],[\"name/41\",[40,47.716]],[\"comment/41\",[]],[\"name/42\",[41,72.839]],[\"comment/42\",[]],[\"name/43\",[42,72.839]],[\"comment/43\",[]],[\"name/44\",[43,72.839]],[\"comment/44\",[]],[\"name/45\",[44,72.839]],[\"comment/45\",[]],[\"name/46\",[45,72.839]],[\"comment/46\",[]],[\"name/47\",[46,72.839]],[\"comment/47\",[]],[\"name/48\",[47,72.839]],[\"comment/48\",[]],[\"name/49\",[48,72.839]],[\"comment/49\",[]],[\"name/50\",[49,72.839]],[\"comment/50\",[]],[\"name/51\",[50,72.839]],[\"comment/51\",[]],[\"name/52\",[51,33.521]],[\"comment/52\",[]],[\"name/53\",[52,59.846]],[\"comment/53\",[]],[\"name/54\",[53,67.731]],[\"comment/54\",[]],[\"name/55\",[54,67.731]],[\"comment/55\",[]],[\"name/56\",[3,64.366]],[\"comment/56\",[]],[\"name/57\",[1,64.366]],[\"comment/57\",[]],[\"name/58\",[55,64.366]],[\"comment/58\",[]],[\"name/59\",[56,67.731]],[\"comment/59\",[]],[\"name/60\",[57,51.636]],[\"comment/60\",[]],[\"name/61\",[58,56.745]],[\"comment/61\",[]],[\"name/62\",[14,59.846]],[\"comment/62\",[]],[\"name/63\",[59,67.731]],[\"comment/63\",[]],[\"name/64\",[60,56.745]],[\"comment/64\",[]],[\"name/65\",[61,67.731]],[\"comment/65\",[]],[\"name/66\",[62,58.176]],[\"comment/66\",[]],[\"name/67\",[2,61.853]],[\"comment/67\",[]],[\"name/68\",[63,64.366]],[\"comment/68\",[]],[\"name/69\",[64,64.366]],[\"comment/69\",[]],[\"name/70\",[65,64.366]],[\"comment/70\",[]],[\"name/71\",[66,64.366]],[\"comment/71\",[]],[\"name/72\",[67,56.745]],[\"comment/72\",[]],[\"name/73\",[68,64.366]],[\"comment/73\",[]],[\"name/74\",[55,64.366]],[\"comment/74\",[]],[\"name/75\",[51,33.521]],[\"comment/75\",[]],[\"name/76\",[61,67.731]],[\"comment/76\",[]],[\"name/77\",[55,64.366]],[\"comment/77\",[]],[\"name/78\",[56,67.731]],[\"comment/78\",[]],[\"name/79\",[60,56.745]],[\"comment/79\",[]],[\"name/80\",[57,51.636]],[\"comment/80\",[]],[\"name/81\",[58,56.745]],[\"comment/81\",[]],[\"name/82\",[14,59.846]],[\"comment/82\",[]],[\"name/83\",[59,67.731]],[\"comment/83\",[]],[\"name/84\",[52,59.846]],[\"comment/84\",[]],[\"name/85\",[53,67.731]],[\"comment/85\",[]],[\"name/86\",[54,67.731]],[\"comment/86\",[]],[\"name/87\",[3,64.366]],[\"comment/87\",[]],[\"name/88\",[1,64.366]],[\"comment/88\",[]],[\"name/89\",[62,58.176]],[\"comment/89\",[]],[\"name/90\",[2,61.853]],[\"comment/90\",[]],[\"name/91\",[63,64.366]],[\"comment/91\",[]],[\"name/92\",[64,64.366]],[\"comment/92\",[]],[\"name/93\",[65,64.366]],[\"comment/93\",[]],[\"name/94\",[66,64.366]],[\"comment/94\",[]],[\"name/95\",[67,56.745]],[\"comment/95\",[]],[\"name/96\",[68,64.366]],[\"comment/96\",[]],[\"name/97\",[69,72.839]],[\"comment/97\",[]],[\"name/98\",[70,72.839]],[\"comment/98\",[]],[\"name/99\",[71,67.731]],[\"comment/99\",[]],[\"name/100\",[72,47.716]],[\"comment/100\",[]],[\"name/101\",[73,64.366]],[\"comment/101\",[]],[\"name/102\",[74,72.839]],[\"comment/102\",[]],[\"name/103\",[73,64.366]],[\"comment/103\",[]],[\"name/104\",[75,59.846]],[\"comment/104\",[]],[\"name/105\",[76,67.731]],[\"comment/105\",[]],[\"name/106\",[77,72.839]],[\"comment/106\",[]],[\"name/107\",[51,33.521]],[\"comment/107\",[]],[\"name/108\",[78,47.716]],[\"comment/108\",[]],[\"name/109\",[79,72.839]],[\"comment/109\",[]],[\"name/110\",[51,33.521]],[\"comment/110\",[]],[\"name/111\",[80,72.839]],[\"comment/111\",[]],[\"name/112\",[78,47.716]],[\"comment/112\",[]],[\"name/113\",[81,72.839]],[\"comment/113\",[]],[\"name/114\",[51,33.521]],[\"comment/114\",[]],[\"name/115\",[2,61.853]],[\"comment/115\",[]],[\"name/116\",[63,64.366]],[\"comment/116\",[]],[\"name/117\",[64,64.366]],[\"comment/117\",[]],[\"name/118\",[65,64.366]],[\"comment/118\",[]],[\"name/119\",[66,64.366]],[\"comment/119\",[]],[\"name/120\",[67,56.745]],[\"comment/120\",[]],[\"name/121\",[68,64.366]],[\"comment/121\",[]],[\"name/122\",[57,51.636]],[\"comment/122\",[]],[\"name/123\",[58,56.745]],[\"comment/123\",[]],[\"name/124\",[14,59.846]],[\"comment/124\",[]],[\"name/125\",[82,72.839]],[\"comment/125\",[]],[\"name/126\",[72,47.716]],[\"comment/126\",[]],[\"name/127\",[83,67.731]],[\"comment/127\",[]],[\"name/128\",[84,72.839]],[\"comment/128\",[]],[\"name/129\",[85,72.839]],[\"comment/129\",[]],[\"name/130\",[86,54.381]],[\"comment/130\",[]],[\"name/131\",[87,72.839]],[\"comment/131\",[]],[\"name/132\",[88,42.394]],[\"comment/132\",[]],[\"name/133\",[89,72.839]],[\"comment/133\",[]],[\"name/134\",[86,54.381]],[\"comment/134\",[]],[\"name/135\",[90,67.731]],[\"comment/135\",[]],[\"name/136\",[88,42.394]],[\"comment/136\",[]],[\"name/137\",[91,72.839]],[\"comment/137\",[]],[\"name/138\",[51,33.521]],[\"comment/138\",[]],[\"name/139\",[92,58.176]],[\"comment/139\",[]],[\"name/140\",[93,52.47]],[\"comment/140\",[]],[\"name/141\",[88,42.394]],[\"comment/141\",[]],[\"name/142\",[94,72.839]],[\"comment/142\",[]],[\"name/143\",[51,33.521]],[\"comment/143\",[]],[\"name/144\",[88,42.394]],[\"comment/144\",[]],[\"name/145\",[95,72.839]],[\"comment/145\",[]],[\"name/146\",[96,51.636]],[\"comment/146\",[]],[\"name/147\",[97,58.176]],[\"comment/147\",[]],[\"name/148\",[98,58.176]],[\"comment/148\",[]],[\"name/149\",[99,58.176]],[\"comment/149\",[]],[\"name/150\",[100,58.176]],[\"comment/150\",[]],[\"name/151\",[101,58.176]],[\"comment/151\",[]],[\"name/152\",[102,58.176]],[\"comment/152\",[]],[\"name/153\",[103,58.176]],[\"comment/153\",[]],[\"name/154\",[104,58.176]],[\"comment/154\",[]],[\"name/155\",[105,72.839]],[\"comment/155\",[]],[\"name/156\",[40,47.716]],[\"comment/156\",[]],[\"name/157\",[106,72.839]],[\"comment/157\",[]],[\"name/158\",[107,56.745]],[\"comment/158\",[]],[\"name/159\",[108,61.853]],[\"comment/159\",[]],[\"name/160\",[109,72.839]],[\"comment/160\",[]],[\"name/161\",[110,61.853]],[\"comment/161\",[]],[\"name/162\",[111,67.731]],[\"comment/162\",[]],[\"name/163\",[112,67.731]],[\"comment/163\",[]],[\"name/164\",[113,67.731]],[\"comment/164\",[]],[\"name/165\",[114,67.731]],[\"comment/165\",[]],[\"name/166\",[115,67.731]],[\"comment/166\",[]],[\"name/167\",[116,67.731]],[\"comment/167\",[]],[\"name/168\",[117,67.731]],[\"comment/168\",[]],[\"name/169\",[118,72.839]],[\"comment/169\",[]],[\"name/170\",[40,47.716]],[\"comment/170\",[]],[\"name/171\",[119,72.839]],[\"comment/171\",[]],[\"name/172\",[51,33.521]],[\"comment/172\",[]],[\"name/173\",[96,51.636]],[\"comment/173\",[]],[\"name/174\",[97,58.176]],[\"comment/174\",[]],[\"name/175\",[98,58.176]],[\"comment/175\",[]],[\"name/176\",[99,58.176]],[\"comment/176\",[]],[\"name/177\",[100,58.176]],[\"comment/177\",[]],[\"name/178\",[101,58.176]],[\"comment/178\",[]],[\"name/179\",[102,58.176]],[\"comment/179\",[]],[\"name/180\",[103,58.176]],[\"comment/180\",[]],[\"name/181\",[110,61.853]],[\"comment/181\",[]],[\"name/182\",[111,67.731]],[\"comment/182\",[]],[\"name/183\",[112,67.731]],[\"comment/183\",[]],[\"name/184\",[113,67.731]],[\"comment/184\",[]],[\"name/185\",[114,67.731]],[\"comment/185\",[]],[\"name/186\",[120,72.839]],[\"comment/186\",[]],[\"name/187\",[115,67.731]],[\"comment/187\",[]],[\"name/188\",[116,67.731]],[\"comment/188\",[]],[\"name/189\",[117,67.731]],[\"comment/189\",[]],[\"name/190\",[121,72.839]],[\"comment/190\",[]],[\"name/191\",[122,67.731]],[\"comment/191\",[]],[\"name/192\",[123,64.366]],[\"comment/192\",[]],[\"name/193\",[124,64.366]],[\"comment/193\",[]],[\"name/194\",[125,64.366]],[\"comment/194\",[]],[\"name/195\",[126,72.839]],[\"comment/195\",[]],[\"name/196\",[127,72.839]],[\"comment/196\",[]],[\"name/197\",[128,72.839]],[\"comment/197\",[]],[\"name/198\",[129,72.839]],[\"comment/198\",[]],[\"name/199\",[130,72.839]],[\"comment/199\",[]],[\"name/200\",[131,72.839]],[\"comment/200\",[]],[\"name/201\",[132,72.839]],[\"comment/201\",[]],[\"name/202\",[133,64.366]],[\"comment/202\",[]],[\"name/203\",[134,64.366]],[\"comment/203\",[]],[\"name/204\",[135,64.366]],[\"comment/204\",[]],[\"name/205\",[136,64.366]],[\"comment/205\",[]],[\"name/206\",[137,72.839]],[\"comment/206\",[]],[\"name/207\",[138,72.839]],[\"comment/207\",[]],[\"name/208\",[139,58.176]],[\"comment/208\",[]],[\"name/209\",[140,64.366]],[\"comment/209\",[]],[\"name/210\",[141,59.846]],[\"comment/210\",[]],[\"name/211\",[142,64.366]],[\"comment/211\",[]],[\"name/212\",[143,72.839]],[\"comment/212\",[]],[\"name/213\",[144,72.839]],[\"comment/213\",[]],[\"name/214\",[145,72.839]],[\"comment/214\",[]],[\"name/215\",[146,72.839]],[\"comment/215\",[]],[\"name/216\",[147,72.839]],[\"comment/216\",[]],[\"name/217\",[148,72.839]],[\"comment/217\",[]],[\"name/218\",[92,58.176]],[\"comment/218\",[]],[\"name/219\",[149,72.839]],[\"comment/219\",[]],[\"name/220\",[104,58.176]],[\"comment/220\",[]],[\"name/221\",[150,72.839]],[\"comment/221\",[]],[\"name/222\",[151,72.839]],[\"comment/222\",[]],[\"name/223\",[152,72.839]],[\"comment/223\",[]],[\"name/224\",[153,43.05]],[\"comment/224\",[]],[\"name/225\",[153,43.05]],[\"comment/225\",[]],[\"name/226\",[154,55.493]],[\"comment/226\",[]],[\"name/227\",[154,55.493]],[\"comment/227\",[]],[\"name/228\",[93,52.47]],[\"comment/228\",[]],[\"name/229\",[93,52.47]],[\"comment/229\",[]],[\"name/230\",[155,61.853]],[\"comment/230\",[]],[\"name/231\",[156,55.493]],[\"comment/231\",[]],[\"name/232\",[156,55.493]],[\"comment/232\",[]],[\"name/233\",[57,51.636]],[\"comment/233\",[]],[\"name/234\",[88,42.394]],[\"comment/234\",[]],[\"name/235\",[157,48.272]],[\"comment/235\",[]],[\"name/236\",[78,47.716]],[\"comment/236\",[]],[\"name/237\",[158,61.853]],[\"comment/237\",[]],[\"name/238\",[159,61.853]],[\"comment/238\",[]],[\"name/239\",[160,54.381]],[\"comment/239\",[]],[\"name/240\",[161,54.381]],[\"comment/240\",[]],[\"name/241\",[162,72.839]],[\"comment/241\",[]],[\"name/242\",[163,47.19]],[\"comment/242\",[]],[\"name/243\",[164,59.846]],[\"comment/243\",[]],[\"name/244\",[72,47.716]],[\"comment/244\",[]],[\"name/245\",[165,72.839]],[\"comment/245\",[]],[\"name/246\",[51,33.521]],[\"comment/246\",[]],[\"name/247\",[88,42.394]],[\"comment/247\",[]],[\"name/248\",[166,72.839]],[\"comment/248\",[]],[\"name/249\",[167,72.839]],[\"comment/249\",[]],[\"name/250\",[168,72.839]],[\"comment/250\",[]],[\"name/251\",[169,72.839]],[\"comment/251\",[]],[\"name/252\",[170,72.839]],[\"comment/252\",[]],[\"name/253\",[51,33.521]],[\"comment/253\",[]],[\"name/254\",[171,59.846]],[\"comment/254\",[]],[\"name/255\",[172,49.485]],[\"comment/255\",[]],[\"name/256\",[86,54.381]],[\"comment/256\",[]],[\"name/257\",[173,67.731]],[\"comment/257\",[]],[\"name/258\",[174,67.731]],[\"comment/258\",[]],[\"name/259\",[175,72.839]],[\"comment/259\",[]],[\"name/260\",[107,56.745]],[\"comment/260\",[]],[\"name/261\",[108,61.853]],[\"comment/261\",[]],[\"name/262\",[153,43.05]],[\"comment/262\",[]],[\"name/263\",[153,43.05]],[\"comment/263\",[]],[\"name/264\",[154,55.493]],[\"comment/264\",[]],[\"name/265\",[154,55.493]],[\"comment/265\",[]],[\"name/266\",[93,52.47]],[\"comment/266\",[]],[\"name/267\",[93,52.47]],[\"comment/267\",[]],[\"name/268\",[155,61.853]],[\"comment/268\",[]],[\"name/269\",[156,55.493]],[\"comment/269\",[]],[\"name/270\",[156,55.493]],[\"comment/270\",[]],[\"name/271\",[57,51.636]],[\"comment/271\",[]],[\"name/272\",[88,42.394]],[\"comment/272\",[]],[\"name/273\",[157,48.272]],[\"comment/273\",[]],[\"name/274\",[78,47.716]],[\"comment/274\",[]],[\"name/275\",[158,61.853]],[\"comment/275\",[]],[\"name/276\",[159,61.853]],[\"comment/276\",[]],[\"name/277\",[160,54.381]],[\"comment/277\",[]],[\"name/278\",[161,54.381]],[\"comment/278\",[]],[\"name/279\",[176,72.839]],[\"comment/279\",[]],[\"name/280\",[163,47.19]],[\"comment/280\",[]],[\"name/281\",[164,59.846]],[\"comment/281\",[]],[\"name/282\",[72,47.716]],[\"comment/282\",[]],[\"name/283\",[177,72.839]],[\"comment/283\",[]],[\"name/284\",[51,33.521]],[\"comment/284\",[]],[\"name/285\",[96,51.636]],[\"comment/285\",[]],[\"name/286\",[97,58.176]],[\"comment/286\",[]],[\"name/287\",[98,58.176]],[\"comment/287\",[]],[\"name/288\",[99,58.176]],[\"comment/288\",[]],[\"name/289\",[100,58.176]],[\"comment/289\",[]],[\"name/290\",[101,58.176]],[\"comment/290\",[]],[\"name/291\",[102,58.176]],[\"comment/291\",[]],[\"name/292\",[103,58.176]],[\"comment/292\",[]],[\"name/293\",[104,58.176]],[\"comment/293\",[]],[\"name/294\",[178,61.853]],[\"comment/294\",[]],[\"name/295\",[133,64.366]],[\"comment/295\",[]],[\"name/296\",[134,64.366]],[\"comment/296\",[]],[\"name/297\",[135,64.366]],[\"comment/297\",[]],[\"name/298\",[136,64.366]],[\"comment/298\",[]],[\"name/299\",[179,72.839]],[\"comment/299\",[]],[\"name/300\",[107,56.745]],[\"comment/300\",[]],[\"name/301\",[108,61.853]],[\"comment/301\",[]],[\"name/302\",[153,43.05]],[\"comment/302\",[]],[\"name/303\",[153,43.05]],[\"comment/303\",[]],[\"name/304\",[154,55.493]],[\"comment/304\",[]],[\"name/305\",[154,55.493]],[\"comment/305\",[]],[\"name/306\",[93,52.47]],[\"comment/306\",[]],[\"name/307\",[93,52.47]],[\"comment/307\",[]],[\"name/308\",[155,61.853]],[\"comment/308\",[]],[\"name/309\",[156,55.493]],[\"comment/309\",[]],[\"name/310\",[156,55.493]],[\"comment/310\",[]],[\"name/311\",[57,51.636]],[\"comment/311\",[]],[\"name/312\",[88,42.394]],[\"comment/312\",[]],[\"name/313\",[157,48.272]],[\"comment/313\",[]],[\"name/314\",[78,47.716]],[\"comment/314\",[]],[\"name/315\",[158,61.853]],[\"comment/315\",[]],[\"name/316\",[159,61.853]],[\"comment/316\",[]],[\"name/317\",[160,54.381]],[\"comment/317\",[]],[\"name/318\",[161,54.381]],[\"comment/318\",[]],[\"name/319\",[180,72.839]],[\"comment/319\",[]],[\"name/320\",[163,47.19]],[\"comment/320\",[]],[\"name/321\",[164,59.846]],[\"comment/321\",[]],[\"name/322\",[72,47.716]],[\"comment/322\",[]],[\"name/323\",[181,72.839]],[\"comment/323\",[]],[\"name/324\",[182,72.839]],[\"comment/324\",[]],[\"name/325\",[183,72.839]],[\"comment/325\",[]],[\"name/326\",[184,72.839]],[\"comment/326\",[]],[\"name/327\",[185,72.839]],[\"comment/327\",[]],[\"name/328\",[51,33.521]],[\"comment/328\",[]],[\"name/329\",[96,51.636]],[\"comment/329\",[]],[\"name/330\",[97,58.176]],[\"comment/330\",[]],[\"name/331\",[98,58.176]],[\"comment/331\",[]],[\"name/332\",[99,58.176]],[\"comment/332\",[]],[\"name/333\",[100,58.176]],[\"comment/333\",[]],[\"name/334\",[101,58.176]],[\"comment/334\",[]],[\"name/335\",[102,58.176]],[\"comment/335\",[]],[\"name/336\",[103,58.176]],[\"comment/336\",[]],[\"name/337\",[104,58.176]],[\"comment/337\",[]],[\"name/338\",[186,61.853]],[\"comment/338\",[]],[\"name/339\",[133,64.366]],[\"comment/339\",[]],[\"name/340\",[134,64.366]],[\"comment/340\",[]],[\"name/341\",[135,64.366]],[\"comment/341\",[]],[\"name/342\",[136,64.366]],[\"comment/342\",[]],[\"name/343\",[107,56.745]],[\"comment/343\",[]],[\"name/344\",[108,61.853]],[\"comment/344\",[]],[\"name/345\",[139,58.176]],[\"comment/345\",[]],[\"name/346\",[141,59.846]],[\"comment/346\",[]],[\"name/347\",[153,43.05]],[\"comment/347\",[]],[\"name/348\",[153,43.05]],[\"comment/348\",[]],[\"name/349\",[154,55.493]],[\"comment/349\",[]],[\"name/350\",[154,55.493]],[\"comment/350\",[]],[\"name/351\",[93,52.47]],[\"comment/351\",[]],[\"name/352\",[93,52.47]],[\"comment/352\",[]],[\"name/353\",[155,61.853]],[\"comment/353\",[]],[\"name/354\",[156,55.493]],[\"comment/354\",[]],[\"name/355\",[156,55.493]],[\"comment/355\",[]],[\"name/356\",[57,51.636]],[\"comment/356\",[]],[\"name/357\",[88,42.394]],[\"comment/357\",[]],[\"name/358\",[157,48.272]],[\"comment/358\",[]],[\"name/359\",[78,47.716]],[\"comment/359\",[]],[\"name/360\",[158,61.853]],[\"comment/360\",[]],[\"name/361\",[159,61.853]],[\"comment/361\",[]],[\"name/362\",[160,54.381]],[\"comment/362\",[]],[\"name/363\",[161,54.381]],[\"comment/363\",[]],[\"name/364\",[187,72.839]],[\"comment/364\",[]],[\"name/365\",[163,47.19]],[\"comment/365\",[]],[\"name/366\",[164,59.846]],[\"comment/366\",[]],[\"name/367\",[72,47.716]],[\"comment/367\",[]],[\"name/368\",[188,72.839]],[\"comment/368\",[]],[\"name/369\",[189,72.839]],[\"comment/369\",[]],[\"name/370\",[190,72.839]],[\"comment/370\",[]],[\"name/371\",[191,72.839]],[\"comment/371\",[]],[\"name/372\",[192,72.839]],[\"comment/372\",[]],[\"name/373\",[193,72.839]],[\"comment/373\",[]],[\"name/374\",[40,47.716]],[\"comment/374\",[]],[\"name/375\",[194,72.839]],[\"comment/375\",[]],[\"name/376\",[51,33.521]],[\"comment/376\",[]],[\"name/377\",[195,48.86]],[\"comment/377\",[]],[\"name/378\",[196,72.839]],[\"comment/378\",[]],[\"name/379\",[51,33.521]],[\"comment/379\",[]],[\"name/380\",[197,59.846]],[\"comment/380\",[]],[\"name/381\",[198,72.839]],[\"comment/381\",[]],[\"name/382\",[199,72.839]],[\"comment/382\",[]],[\"name/383\",[200,72.839]],[\"comment/383\",[]],[\"name/384\",[201,72.839]],[\"comment/384\",[]],[\"name/385\",[202,72.839]],[\"comment/385\",[]],[\"name/386\",[203,72.839]],[\"comment/386\",[]],[\"name/387\",[204,72.839]],[\"comment/387\",[]],[\"name/388\",[205,72.839]],[\"comment/388\",[]],[\"name/389\",[153,43.05]],[\"comment/389\",[]],[\"name/390\",[88,42.394]],[\"comment/390\",[]],[\"name/391\",[206,72.839]],[\"comment/391\",[]],[\"name/392\",[207,67.731]],[\"comment/392\",[]],[\"name/393\",[208,72.839]],[\"comment/393\",[]],[\"name/394\",[209,72.839]],[\"comment/394\",[]],[\"name/395\",[210,72.839]],[\"comment/395\",[]],[\"name/396\",[211,72.839]],[\"comment/396\",[]],[\"name/397\",[212,72.839]],[\"comment/397\",[]],[\"name/398\",[213,72.839]],[\"comment/398\",[]],[\"name/399\",[214,72.839]],[\"comment/399\",[]],[\"name/400\",[215,72.839]],[\"comment/400\",[]],[\"name/401\",[216,72.839]],[\"comment/401\",[]],[\"name/402\",[217,72.839]],[\"comment/402\",[]],[\"name/403\",[218,72.839]],[\"comment/403\",[]],[\"name/404\",[51,33.521]],[\"comment/404\",[]],[\"name/405\",[219,64.366]],[\"comment/405\",[]],[\"name/406\",[220,72.839]],[\"comment/406\",[]],[\"name/407\",[221,72.839]],[\"comment/407\",[]],[\"name/408\",[51,33.521]],[\"comment/408\",[]],[\"name/409\",[222,72.839]],[\"comment/409\",[]],[\"name/410\",[223,72.839]],[\"comment/410\",[]],[\"name/411\",[51,33.521]],[\"comment/411\",[]],[\"name/412\",[224,72.839]],[\"comment/412\",[]],[\"name/413\",[225,72.839]],[\"comment/413\",[]],[\"name/414\",[51,33.521]],[\"comment/414\",[]],[\"name/415\",[226,52.47]],[\"comment/415\",[]],[\"name/416\",[172,49.485]],[\"comment/416\",[]],[\"name/417\",[227,64.366]],[\"comment/417\",[]],[\"name/418\",[86,54.381]],[\"comment/418\",[]],[\"name/419\",[96,51.636]],[\"comment/419\",[]],[\"name/420\",[97,58.176]],[\"comment/420\",[]],[\"name/421\",[98,58.176]],[\"comment/421\",[]],[\"name/422\",[99,58.176]],[\"comment/422\",[]],[\"name/423\",[100,58.176]],[\"comment/423\",[]],[\"name/424\",[101,58.176]],[\"comment/424\",[]],[\"name/425\",[102,58.176]],[\"comment/425\",[]],[\"name/426\",[103,58.176]],[\"comment/426\",[]],[\"name/427\",[104,58.176]],[\"comment/427\",[]],[\"name/428\",[228,67.731]],[\"comment/428\",[]],[\"name/429\",[229,72.839]],[\"comment/429\",[]],[\"name/430\",[153,43.05]],[\"comment/430\",[]],[\"name/431\",[230,72.839]],[\"comment/431\",[]],[\"name/432\",[231,67.731]],[\"comment/432\",[]],[\"name/433\",[232,72.839]],[\"comment/433\",[]],[\"name/434\",[233,72.839]],[\"comment/434\",[]],[\"name/435\",[234,72.839]],[\"comment/435\",[]],[\"name/436\",[51,33.521]],[\"comment/436\",[]],[\"name/437\",[88,42.394]],[\"comment/437\",[]],[\"name/438\",[235,72.839]],[\"comment/438\",[]],[\"name/439\",[51,33.521]],[\"comment/439\",[]],[\"name/440\",[96,51.636]],[\"comment/440\",[]],[\"name/441\",[97,58.176]],[\"comment/441\",[]],[\"name/442\",[98,58.176]],[\"comment/442\",[]],[\"name/443\",[99,58.176]],[\"comment/443\",[]],[\"name/444\",[100,58.176]],[\"comment/444\",[]],[\"name/445\",[101,58.176]],[\"comment/445\",[]],[\"name/446\",[102,58.176]],[\"comment/446\",[]],[\"name/447\",[103,58.176]],[\"comment/447\",[]],[\"name/448\",[104,58.176]],[\"comment/448\",[]],[\"name/449\",[153,43.05]],[\"comment/449\",[]],[\"name/450\",[88,42.394]],[\"comment/450\",[]],[\"name/451\",[236,72.839]],[\"comment/451\",[]],[\"name/452\",[51,33.521]],[\"comment/452\",[]],[\"name/453\",[92,58.176]],[\"comment/453\",[]],[\"name/454\",[125,64.366]],[\"comment/454\",[]],[\"name/455\",[237,72.839]],[\"comment/455\",[]],[\"name/456\",[238,72.839]],[\"comment/456\",[]],[\"name/457\",[239,72.839]],[\"comment/457\",[]],[\"name/458\",[240,72.839]],[\"comment/458\",[]],[\"name/459\",[241,72.839]],[\"comment/459\",[]],[\"name/460\",[242,72.839]],[\"comment/460\",[]],[\"name/461\",[243,72.839]],[\"comment/461\",[]],[\"name/462\",[244,72.839]],[\"comment/462\",[]],[\"name/463\",[245,67.731]],[\"comment/463\",[]],[\"name/464\",[153,43.05]],[\"comment/464\",[]],[\"name/465\",[88,42.394]],[\"comment/465\",[]],[\"name/466\",[246,72.839]],[\"comment/466\",[]],[\"name/467\",[51,33.521]],[\"comment/467\",[]],[\"name/468\",[88,42.394]],[\"comment/468\",[]],[\"name/469\",[247,72.839]],[\"comment/469\",[]],[\"name/470\",[248,67.731]],[\"comment/470\",[]],[\"name/471\",[249,72.839]],[\"comment/471\",[]],[\"name/472\",[40,47.716]],[\"comment/472\",[]],[\"name/473\",[250,72.839]],[\"comment/473\",[]],[\"name/474\",[51,33.521]],[\"comment/474\",[]],[\"name/475\",[251,64.366]],[\"comment/475\",[]],[\"name/476\",[252,72.839]],[\"comment/476\",[]],[\"name/477\",[51,33.521]],[\"comment/477\",[]],[\"name/478\",[253,72.839]],[\"comment/478\",[]],[\"name/479\",[254,72.839]],[\"comment/479\",[]],[\"name/480\",[51,33.521]],[\"comment/480\",[]],[\"name/481\",[251,64.366]],[\"comment/481\",[]],[\"name/482\",[255,67.731]],[\"comment/482\",[]],[\"name/483\",[256,61.853]],[\"comment/483\",[]],[\"name/484\",[257,67.731]],[\"comment/484\",[]],[\"name/485\",[258,72.839]],[\"comment/485\",[]],[\"name/486\",[51,33.521]],[\"comment/486\",[]],[\"name/487\",[256,61.853]],[\"comment/487\",[]],[\"name/488\",[257,67.731]],[\"comment/488\",[]],[\"name/489\",[259,72.839]],[\"comment/489\",[]],[\"name/490\",[260,72.839]],[\"comment/490\",[]],[\"name/491\",[51,33.521]],[\"comment/491\",[]],[\"name/492\",[92,58.176]],[\"comment/492\",[]],[\"name/493\",[93,52.47]],[\"comment/493\",[]],[\"name/494\",[93,52.47]],[\"comment/494\",[]],[\"name/495\",[57,51.636]],[\"comment/495\",[]],[\"name/496\",[88,42.394]],[\"comment/496\",[]],[\"name/497\",[157,48.272]],[\"comment/497\",[]],[\"name/498\",[78,47.716]],[\"comment/498\",[]],[\"name/499\",[261,72.839]],[\"comment/499\",[]],[\"name/500\",[51,33.521]],[\"comment/500\",[]],[\"name/501\",[88,42.394]],[\"comment/501\",[]],[\"name/502\",[262,72.839]],[\"comment/502\",[]],[\"name/503\",[163,47.19]],[\"comment/503\",[]],[\"name/504\",[263,67.731]],[\"comment/504\",[]],[\"name/505\",[75,59.846]],[\"comment/505\",[]],[\"name/506\",[264,64.366]],[\"comment/506\",[]],[\"name/507\",[5,67.731]],[\"comment/507\",[]],[\"name/508\",[265,61.853]],[\"comment/508\",[]],[\"name/509\",[4,64.366]],[\"comment/509\",[]],[\"name/510\",[266,51.636]],[\"comment/510\",[]],[\"name/511\",[267,72.839]],[\"comment/511\",[]],[\"name/512\",[268,72.839]],[\"comment/512\",[]],[\"name/513\",[269,72.839]],[\"comment/513\",[]],[\"name/514\",[270,72.839]],[\"comment/514\",[]],[\"name/515\",[271,67.731]],[\"comment/515\",[]],[\"name/516\",[264,64.366]],[\"comment/516\",[]],[\"name/517\",[272,72.839]],[\"comment/517\",[]],[\"name/518\",[273,64.366]],[\"comment/518\",[]],[\"name/519\",[75,59.846]],[\"comment/519\",[]],[\"name/520\",[274,56.745]],[\"comment/520\",[]],[\"name/521\",[275,55.493]],[\"comment/521\",[]],[\"name/522\",[62,58.176]],[\"comment/522\",[]],[\"name/523\",[160,54.381]],[\"comment/523\",[]],[\"name/524\",[276,64.366]],[\"comment/524\",[]],[\"name/525\",[57,51.636]],[\"comment/525\",[]],[\"name/526\",[277,64.366]],[\"comment/526\",[]],[\"name/527\",[278,64.366]],[\"comment/527\",[]],[\"name/528\",[58,56.745]],[\"comment/528\",[]],[\"name/529\",[279,58.176]],[\"comment/529\",[]],[\"name/530\",[280,72.839]],[\"comment/530\",[]],[\"name/531\",[51,33.521]],[\"comment/531\",[]],[\"name/532\",[273,64.366]],[\"comment/532\",[]],[\"name/533\",[275,55.493]],[\"comment/533\",[]],[\"name/534\",[279,58.176]],[\"comment/534\",[]],[\"name/535\",[277,64.366]],[\"comment/535\",[]],[\"name/536\",[57,51.636]],[\"comment/536\",[]],[\"name/537\",[278,64.366]],[\"comment/537\",[]],[\"name/538\",[276,64.366]],[\"comment/538\",[]],[\"name/539\",[58,56.745]],[\"comment/539\",[]],[\"name/540\",[75,59.846]],[\"comment/540\",[]],[\"name/541\",[274,56.745]],[\"comment/541\",[]],[\"name/542\",[62,58.176]],[\"comment/542\",[]],[\"name/543\",[160,54.381]],[\"comment/543\",[]],[\"name/544\",[281,72.839]],[\"comment/544\",[]],[\"name/545\",[51,33.521]],[\"comment/545\",[]],[\"name/546\",[273,64.366]],[\"comment/546\",[]],[\"name/547\",[275,55.493]],[\"comment/547\",[]],[\"name/548\",[279,58.176]],[\"comment/548\",[]],[\"name/549\",[276,64.366]],[\"comment/549\",[]],[\"name/550\",[57,51.636]],[\"comment/550\",[]],[\"name/551\",[277,64.366]],[\"comment/551\",[]],[\"name/552\",[278,64.366]],[\"comment/552\",[]],[\"name/553\",[58,56.745]],[\"comment/553\",[]],[\"name/554\",[75,59.846]],[\"comment/554\",[]],[\"name/555\",[274,56.745]],[\"comment/555\",[]],[\"name/556\",[62,58.176]],[\"comment/556\",[]],[\"name/557\",[160,54.381]],[\"comment/557\",[]],[\"name/558\",[282,72.839]],[\"comment/558\",[]],[\"name/559\",[283,72.839]],[\"comment/559\",[]],[\"name/560\",[51,33.521]],[\"comment/560\",[]],[\"name/561\",[284,61.853]],[\"comment/561\",[]],[\"name/562\",[275,55.493]],[\"comment/562\",[]],[\"name/563\",[285,61.853]],[\"comment/563\",[]],[\"name/564\",[286,59.846]],[\"comment/564\",[]],[\"name/565\",[287,59.846]],[\"comment/565\",[]],[\"name/566\",[288,59.846]],[\"comment/566\",[]],[\"name/567\",[289,59.846]],[\"comment/567\",[]],[\"name/568\",[290,61.853]],[\"comment/568\",[]],[\"name/569\",[291,61.853]],[\"comment/569\",[]],[\"name/570\",[292,59.846]],[\"comment/570\",[]],[\"name/571\",[293,59.846]],[\"comment/571\",[]],[\"name/572\",[294,59.846]],[\"comment/572\",[]],[\"name/573\",[295,59.846]],[\"comment/573\",[]],[\"name/574\",[296,59.846]],[\"comment/574\",[]],[\"name/575\",[297,59.846]],[\"comment/575\",[]],[\"name/576\",[298,59.846]],[\"comment/576\",[]],[\"name/577\",[299,59.846]],[\"comment/577\",[]],[\"name/578\",[300,59.846]],[\"comment/578\",[]],[\"name/579\",[301,59.846]],[\"comment/579\",[]],[\"name/580\",[302,61.853]],[\"comment/580\",[]],[\"name/581\",[303,59.846]],[\"comment/581\",[]],[\"name/582\",[304,59.846]],[\"comment/582\",[]],[\"name/583\",[305,59.846]],[\"comment/583\",[]],[\"name/584\",[306,59.846]],[\"comment/584\",[]],[\"name/585\",[307,59.846]],[\"comment/585\",[]],[\"name/586\",[308,59.846]],[\"comment/586\",[]],[\"name/587\",[309,59.846]],[\"comment/587\",[]],[\"name/588\",[310,59.846]],[\"comment/588\",[]],[\"name/589\",[311,59.846]],[\"comment/589\",[]],[\"name/590\",[312,59.846]],[\"comment/590\",[]],[\"name/591\",[313,59.846]],[\"comment/591\",[]],[\"name/592\",[314,59.846]],[\"comment/592\",[]],[\"name/593\",[315,59.846]],[\"comment/593\",[]],[\"name/594\",[316,59.846]],[\"comment/594\",[]],[\"name/595\",[317,61.853]],[\"comment/595\",[]],[\"name/596\",[318,59.846]],[\"comment/596\",[]],[\"name/597\",[319,59.846]],[\"comment/597\",[]],[\"name/598\",[320,59.846]],[\"comment/598\",[]],[\"name/599\",[321,59.846]],[\"comment/599\",[]],[\"name/600\",[322,59.846]],[\"comment/600\",[]],[\"name/601\",[323,59.846]],[\"comment/601\",[]],[\"name/602\",[324,59.846]],[\"comment/602\",[]],[\"name/603\",[325,59.846]],[\"comment/603\",[]],[\"name/604\",[326,59.846]],[\"comment/604\",[]],[\"name/605\",[327,59.846]],[\"comment/605\",[]],[\"name/606\",[328,59.846]],[\"comment/606\",[]],[\"name/607\",[329,59.846]],[\"comment/607\",[]],[\"name/608\",[330,59.846]],[\"comment/608\",[]],[\"name/609\",[331,59.846]],[\"comment/609\",[]],[\"name/610\",[332,59.846]],[\"comment/610\",[]],[\"name/611\",[333,59.846]],[\"comment/611\",[]],[\"name/612\",[334,59.846]],[\"comment/612\",[]],[\"name/613\",[335,59.846]],[\"comment/613\",[]],[\"name/614\",[336,59.846]],[\"comment/614\",[]],[\"name/615\",[337,59.846]],[\"comment/615\",[]],[\"name/616\",[338,59.846]],[\"comment/616\",[]],[\"name/617\",[339,59.846]],[\"comment/617\",[]],[\"name/618\",[340,59.846]],[\"comment/618\",[]],[\"name/619\",[341,59.846]],[\"comment/619\",[]],[\"name/620\",[342,59.846]],[\"comment/620\",[]],[\"name/621\",[343,59.846]],[\"comment/621\",[]],[\"name/622\",[344,59.846]],[\"comment/622\",[]],[\"name/623\",[345,59.846]],[\"comment/623\",[]],[\"name/624\",[346,59.846]],[\"comment/624\",[]],[\"name/625\",[347,59.846]],[\"comment/625\",[]],[\"name/626\",[348,59.846]],[\"comment/626\",[]],[\"name/627\",[349,59.846]],[\"comment/627\",[]],[\"name/628\",[350,59.846]],[\"comment/628\",[]],[\"name/629\",[351,59.846]],[\"comment/629\",[]],[\"name/630\",[352,59.846]],[\"comment/630\",[]],[\"name/631\",[353,59.846]],[\"comment/631\",[]],[\"name/632\",[354,59.846]],[\"comment/632\",[]],[\"name/633\",[355,59.846]],[\"comment/633\",[]],[\"name/634\",[356,59.846]],[\"comment/634\",[]],[\"name/635\",[357,59.846]],[\"comment/635\",[]],[\"name/636\",[358,59.846]],[\"comment/636\",[]],[\"name/637\",[359,59.846]],[\"comment/637\",[]],[\"name/638\",[360,59.846]],[\"comment/638\",[]],[\"name/639\",[361,59.846]],[\"comment/639\",[]],[\"name/640\",[362,59.846]],[\"comment/640\",[]],[\"name/641\",[363,59.846]],[\"comment/641\",[]],[\"name/642\",[364,59.846]],[\"comment/642\",[]],[\"name/643\",[365,59.846]],[\"comment/643\",[]],[\"name/644\",[366,59.846]],[\"comment/644\",[]],[\"name/645\",[367,61.853]],[\"comment/645\",[]],[\"name/646\",[368,59.846]],[\"comment/646\",[]],[\"name/647\",[369,59.846]],[\"comment/647\",[]],[\"name/648\",[370,59.846]],[\"comment/648\",[]],[\"name/649\",[371,59.846]],[\"comment/649\",[]],[\"name/650\",[372,61.853]],[\"comment/650\",[]],[\"name/651\",[373,61.853]],[\"comment/651\",[]],[\"name/652\",[374,61.853]],[\"comment/652\",[]],[\"name/653\",[375,61.853]],[\"comment/653\",[]],[\"name/654\",[376,61.853]],[\"comment/654\",[]],[\"name/655\",[377,61.853]],[\"comment/655\",[]],[\"name/656\",[378,61.853]],[\"comment/656\",[]],[\"name/657\",[379,61.853]],[\"comment/657\",[]],[\"name/658\",[380,61.853]],[\"comment/658\",[]],[\"name/659\",[381,61.853]],[\"comment/659\",[]],[\"name/660\",[382,61.853]],[\"comment/660\",[]],[\"name/661\",[383,61.853]],[\"comment/661\",[]],[\"name/662\",[384,58.176]],[\"comment/662\",[]],[\"name/663\",[385,59.846]],[\"comment/663\",[]],[\"name/664\",[386,59.846]],[\"comment/664\",[]],[\"name/665\",[387,67.731]],[\"comment/665\",[]],[\"name/666\",[387,67.731]],[\"comment/666\",[]],[\"name/667\",[388,58.176]],[\"comment/667\",[]],[\"name/668\",[264,64.366]],[\"comment/668\",[]],[\"name/669\",[389,67.731]],[\"comment/669\",[]],[\"name/670\",[390,72.839]],[\"comment/670\",[]],[\"name/671\",[51,33.521]],[\"comment/671\",[]],[\"name/672\",[391,72.839]],[\"comment/672\",[]],[\"name/673\",[392,72.839]],[\"comment/673\",[]],[\"name/674\",[393,72.839]],[\"comment/674\",[]],[\"name/675\",[394,72.839]],[\"comment/675\",[]],[\"name/676\",[395,72.839]],[\"comment/676\",[]],[\"name/677\",[396,72.839]],[\"comment/677\",[]],[\"name/678\",[397,72.839]],[\"comment/678\",[]],[\"name/679\",[398,72.839]],[\"comment/679\",[]],[\"name/680\",[399,72.839]],[\"comment/680\",[]],[\"name/681\",[400,72.839]],[\"comment/681\",[]],[\"name/682\",[401,72.839]],[\"comment/682\",[]],[\"name/683\",[57,51.636]],[\"comment/683\",[]],[\"name/684\",[58,56.745]],[\"comment/684\",[]],[\"name/685\",[14,59.846]],[\"comment/685\",[]],[\"name/686\",[402,72.839]],[\"comment/686\",[]],[\"name/687\",[51,33.521]],[\"comment/687\",[]],[\"name/688\",[403,61.853]],[\"comment/688\",[]],[\"name/689\",[404,67.731]],[\"comment/689\",[]],[\"name/690\",[405,55.493]],[\"comment/690\",[]],[\"name/691\",[406,61.853]],[\"comment/691\",[]],[\"name/692\",[407,72.839]],[\"comment/692\",[]],[\"name/693\",[408,67.731]],[\"comment/693\",[]],[\"name/694\",[409,67.731]],[\"comment/694\",[]],[\"name/695\",[410,67.731]],[\"comment/695\",[]],[\"name/696\",[123,64.366]],[\"comment/696\",[]],[\"name/697\",[124,64.366]],[\"comment/697\",[]],[\"name/698\",[153,43.05]],[\"comment/698\",[]],[\"name/699\",[153,43.05]],[\"comment/699\",[]],[\"name/700\",[88,42.394]],[\"comment/700\",[]],[\"name/701\",[157,48.272]],[\"comment/701\",[]],[\"name/702\",[78,47.716]],[\"comment/702\",[]],[\"name/703\",[411,72.839]],[\"comment/703\",[]],[\"name/704\",[163,47.19]],[\"comment/704\",[]],[\"name/705\",[72,47.716]],[\"comment/705\",[]],[\"name/706\",[195,48.86]],[\"comment/706\",[]],[\"name/707\",[412,72.839]],[\"comment/707\",[]],[\"name/708\",[40,47.716]],[\"comment/708\",[]],[\"name/709\",[413,72.839]],[\"comment/709\",[]],[\"name/710\",[40,47.716]],[\"comment/710\",[]],[\"name/711\",[414,72.839]],[\"comment/711\",[]],[\"name/712\",[51,33.521]],[\"comment/712\",[]],[\"name/713\",[88,42.394]],[\"comment/713\",[]],[\"name/714\",[415,72.839]],[\"comment/714\",[]],[\"name/715\",[153,43.05]],[\"comment/715\",[]],[\"name/716\",[157,48.272]],[\"comment/716\",[]],[\"name/717\",[78,47.716]],[\"comment/717\",[]],[\"name/718\",[416,72.839]],[\"comment/718\",[]],[\"name/719\",[163,47.19]],[\"comment/719\",[]],[\"name/720\",[72,47.716]],[\"comment/720\",[]],[\"name/721\",[195,48.86]],[\"comment/721\",[]],[\"name/722\",[417,72.839]],[\"comment/722\",[]],[\"name/723\",[51,33.521]],[\"comment/723\",[]],[\"name/724\",[418,52.47]],[\"comment/724\",[]],[\"name/725\",[419,55.493]],[\"comment/725\",[]],[\"name/726\",[153,43.05]],[\"comment/726\",[]],[\"name/727\",[88,42.394]],[\"comment/727\",[]],[\"name/728\",[157,48.272]],[\"comment/728\",[]],[\"name/729\",[78,47.716]],[\"comment/729\",[]],[\"name/730\",[420,72.839]],[\"comment/730\",[]],[\"name/731\",[163,47.19]],[\"comment/731\",[]],[\"name/732\",[72,47.716]],[\"comment/732\",[]],[\"name/733\",[195,48.86]],[\"comment/733\",[]],[\"name/734\",[421,72.839]],[\"comment/734\",[]],[\"name/735\",[51,33.521]],[\"comment/735\",[]],[\"name/736\",[418,52.47]],[\"comment/736\",[]],[\"name/737\",[153,43.05]],[\"comment/737\",[]],[\"name/738\",[88,42.394]],[\"comment/738\",[]],[\"name/739\",[157,48.272]],[\"comment/739\",[]],[\"name/740\",[78,47.716]],[\"comment/740\",[]],[\"name/741\",[422,72.839]],[\"comment/741\",[]],[\"name/742\",[163,47.19]],[\"comment/742\",[]],[\"name/743\",[72,47.716]],[\"comment/743\",[]],[\"name/744\",[195,48.86]],[\"comment/744\",[]],[\"name/745\",[423,72.839]],[\"comment/745\",[]],[\"name/746\",[51,33.521]],[\"comment/746\",[]],[\"name/747\",[405,55.493]],[\"comment/747\",[]],[\"name/748\",[424,61.853]],[\"comment/748\",[]],[\"name/749\",[197,59.846]],[\"comment/749\",[]],[\"name/750\",[226,52.47]],[\"comment/750\",[]],[\"name/751\",[172,49.485]],[\"comment/751\",[]],[\"name/752\",[86,54.381]],[\"comment/752\",[]],[\"name/753\",[186,61.853]],[\"comment/753\",[]],[\"name/754\",[96,51.636]],[\"comment/754\",[]],[\"name/755\",[153,43.05]],[\"comment/755\",[]],[\"name/756\",[88,42.394]],[\"comment/756\",[]],[\"name/757\",[157,48.272]],[\"comment/757\",[]],[\"name/758\",[78,47.716]],[\"comment/758\",[]],[\"name/759\",[425,72.839]],[\"comment/759\",[]],[\"name/760\",[163,47.19]],[\"comment/760\",[]],[\"name/761\",[72,47.716]],[\"comment/761\",[]],[\"name/762\",[195,48.86]],[\"comment/762\",[]],[\"name/763\",[426,72.839]],[\"comment/763\",[]],[\"name/764\",[51,33.521]],[\"comment/764\",[]],[\"name/765\",[197,59.846]],[\"comment/765\",[]],[\"name/766\",[418,52.47]],[\"comment/766\",[]],[\"name/767\",[419,55.493]],[\"comment/767\",[]],[\"name/768\",[153,43.05]],[\"comment/768\",[]],[\"name/769\",[88,42.394]],[\"comment/769\",[]],[\"name/770\",[157,48.272]],[\"comment/770\",[]],[\"name/771\",[78,47.716]],[\"comment/771\",[]],[\"name/772\",[427,72.839]],[\"comment/772\",[]],[\"name/773\",[163,47.19]],[\"comment/773\",[]],[\"name/774\",[72,47.716]],[\"comment/774\",[]],[\"name/775\",[195,48.86]],[\"comment/775\",[]],[\"name/776\",[428,72.839]],[\"comment/776\",[]],[\"name/777\",[51,33.521]],[\"comment/777\",[]],[\"name/778\",[405,55.493]],[\"comment/778\",[]],[\"name/779\",[153,43.05]],[\"comment/779\",[]],[\"name/780\",[88,42.394]],[\"comment/780\",[]],[\"name/781\",[157,48.272]],[\"comment/781\",[]],[\"name/782\",[78,47.716]],[\"comment/782\",[]],[\"name/783\",[429,72.839]],[\"comment/783\",[]],[\"name/784\",[163,47.19]],[\"comment/784\",[]],[\"name/785\",[72,47.716]],[\"comment/785\",[]],[\"name/786\",[195,48.86]],[\"comment/786\",[]],[\"name/787\",[430,72.839]],[\"comment/787\",[]],[\"name/788\",[51,33.521]],[\"comment/788\",[]],[\"name/789\",[418,52.47]],[\"comment/789\",[]],[\"name/790\",[419,55.493]],[\"comment/790\",[]],[\"name/791\",[153,43.05]],[\"comment/791\",[]],[\"name/792\",[88,42.394]],[\"comment/792\",[]],[\"name/793\",[157,48.272]],[\"comment/793\",[]],[\"name/794\",[78,47.716]],[\"comment/794\",[]],[\"name/795\",[431,72.839]],[\"comment/795\",[]],[\"name/796\",[163,47.19]],[\"comment/796\",[]],[\"name/797\",[72,47.716]],[\"comment/797\",[]],[\"name/798\",[195,48.86]],[\"comment/798\",[]],[\"name/799\",[432,72.839]],[\"comment/799\",[]],[\"name/800\",[51,33.521]],[\"comment/800\",[]],[\"name/801\",[433,67.731]],[\"comment/801\",[]],[\"name/802\",[434,67.731]],[\"comment/802\",[]],[\"name/803\",[435,64.366]],[\"comment/803\",[]],[\"name/804\",[436,59.846]],[\"comment/804\",[]],[\"name/805\",[437,59.846]],[\"comment/805\",[]],[\"name/806\",[424,61.853]],[\"comment/806\",[]],[\"name/807\",[438,67.731]],[\"comment/807\",[]],[\"name/808\",[439,67.731]],[\"comment/808\",[]],[\"name/809\",[440,67.731]],[\"comment/809\",[]],[\"name/810\",[441,67.731]],[\"comment/810\",[]],[\"name/811\",[442,72.839]],[\"comment/811\",[]],[\"name/812\",[443,72.839]],[\"comment/812\",[]],[\"name/813\",[444,72.839]],[\"comment/813\",[]],[\"name/814\",[445,67.731]],[\"comment/814\",[]],[\"name/815\",[123,64.366]],[\"comment/815\",[]],[\"name/816\",[124,64.366]],[\"comment/816\",[]],[\"name/817\",[153,43.05]],[\"comment/817\",[]],[\"name/818\",[88,42.394]],[\"comment/818\",[]],[\"name/819\",[446,72.839]],[\"comment/819\",[]],[\"name/820\",[40,47.716]],[\"comment/820\",[]],[\"name/821\",[447,72.839]],[\"comment/821\",[]],[\"name/822\",[436,59.846]],[\"comment/822\",[]],[\"name/823\",[437,59.846]],[\"comment/823\",[]],[\"name/824\",[448,72.839]],[\"comment/824\",[]],[\"name/825\",[51,33.521]],[\"comment/825\",[]],[\"name/826\",[436,59.846]],[\"comment/826\",[]],[\"name/827\",[437,59.846]],[\"comment/827\",[]],[\"name/828\",[153,43.05]],[\"comment/828\",[]],[\"name/829\",[88,42.394]],[\"comment/829\",[]],[\"name/830\",[449,72.839]],[\"comment/830\",[]],[\"name/831\",[51,33.521]],[\"comment/831\",[]],[\"name/832\",[450,64.366]],[\"comment/832\",[]],[\"name/833\",[451,67.731]],[\"comment/833\",[]],[\"name/834\",[452,64.366]],[\"comment/834\",[]],[\"name/835\",[453,64.366]],[\"comment/835\",[]],[\"name/836\",[454,64.366]],[\"comment/836\",[]],[\"name/837\",[406,61.853]],[\"comment/837\",[]],[\"name/838\",[455,64.366]],[\"comment/838\",[]],[\"name/839\",[408,67.731]],[\"comment/839\",[]],[\"name/840\",[409,67.731]],[\"comment/840\",[]],[\"name/841\",[410,67.731]],[\"comment/841\",[]],[\"name/842\",[456,67.731]],[\"comment/842\",[]],[\"name/843\",[153,43.05]],[\"comment/843\",[]],[\"name/844\",[153,43.05]],[\"comment/844\",[]],[\"name/845\",[457,72.839]],[\"comment/845\",[]],[\"name/846\",[163,47.19]],[\"comment/846\",[]],[\"name/847\",[72,47.716]],[\"comment/847\",[]],[\"name/848\",[195,48.86]],[\"comment/848\",[]],[\"name/849\",[458,72.839]],[\"comment/849\",[]],[\"name/850\",[452,64.366]],[\"comment/850\",[]],[\"name/851\",[453,64.366]],[\"comment/851\",[]],[\"name/852\",[454,64.366]],[\"comment/852\",[]],[\"name/853\",[406,61.853]],[\"comment/853\",[]],[\"name/854\",[455,64.366]],[\"comment/854\",[]],[\"name/855\",[459,72.839]],[\"comment/855\",[]],[\"name/856\",[51,33.521]],[\"comment/856\",[]],[\"name/857\",[452,64.366]],[\"comment/857\",[]],[\"name/858\",[453,64.366]],[\"comment/858\",[]],[\"name/859\",[454,64.366]],[\"comment/859\",[]],[\"name/860\",[406,61.853]],[\"comment/860\",[]],[\"name/861\",[455,64.366]],[\"comment/861\",[]],[\"name/862\",[88,42.394]],[\"comment/862\",[]],[\"name/863\",[157,48.272]],[\"comment/863\",[]],[\"name/864\",[78,47.716]],[\"comment/864\",[]],[\"name/865\",[460,72.839]],[\"comment/865\",[]],[\"name/866\",[163,47.19]],[\"comment/866\",[]],[\"name/867\",[72,47.716]],[\"comment/867\",[]],[\"name/868\",[195,48.86]],[\"comment/868\",[]],[\"name/869\",[461,72.839]],[\"comment/869\",[]],[\"name/870\",[51,33.521]],[\"comment/870\",[]],[\"name/871\",[403,61.853]],[\"comment/871\",[]],[\"name/872\",[462,61.853]],[\"comment/872\",[]],[\"name/873\",[405,55.493]],[\"comment/873\",[]],[\"name/874\",[463,67.731]],[\"comment/874\",[]],[\"name/875\",[172,49.485]],[\"comment/875\",[]],[\"name/876\",[92,58.176]],[\"comment/876\",[]],[\"name/877\",[153,43.05]],[\"comment/877\",[]],[\"name/878\",[88,42.394]],[\"comment/878\",[]],[\"name/879\",[157,48.272]],[\"comment/879\",[]],[\"name/880\",[78,47.716]],[\"comment/880\",[]],[\"name/881\",[464,72.839]],[\"comment/881\",[]],[\"name/882\",[163,47.19]],[\"comment/882\",[]],[\"name/883\",[72,47.716]],[\"comment/883\",[]],[\"name/884\",[195,48.86]],[\"comment/884\",[]],[\"name/885\",[465,72.839]],[\"comment/885\",[]],[\"name/886\",[51,33.521]],[\"comment/886\",[]],[\"name/887\",[462,61.853]],[\"comment/887\",[]],[\"name/888\",[418,52.47]],[\"comment/888\",[]],[\"name/889\",[419,55.493]],[\"comment/889\",[]],[\"name/890\",[153,43.05]],[\"comment/890\",[]],[\"name/891\",[88,42.394]],[\"comment/891\",[]],[\"name/892\",[157,48.272]],[\"comment/892\",[]],[\"name/893\",[78,47.716]],[\"comment/893\",[]],[\"name/894\",[466,72.839]],[\"comment/894\",[]],[\"name/895\",[163,47.19]],[\"comment/895\",[]],[\"name/896\",[72,47.716]],[\"comment/896\",[]],[\"name/897\",[195,48.86]],[\"comment/897\",[]],[\"name/898\",[467,72.839]],[\"comment/898\",[]],[\"name/899\",[51,33.521]],[\"comment/899\",[]],[\"name/900\",[468,64.366]],[\"comment/900\",[]],[\"name/901\",[469,67.731]],[\"comment/901\",[]],[\"name/902\",[470,64.366]],[\"comment/902\",[]],[\"name/903\",[471,64.366]],[\"comment/903\",[]],[\"name/904\",[472,64.366]],[\"comment/904\",[]],[\"name/905\",[473,64.366]],[\"comment/905\",[]],[\"name/906\",[153,43.05]],[\"comment/906\",[]],[\"name/907\",[474,72.839]],[\"comment/907\",[]],[\"name/908\",[51,33.521]],[\"comment/908\",[]],[\"name/909\",[88,42.394]],[\"comment/909\",[]],[\"name/910\",[468,64.366]],[\"comment/910\",[]],[\"name/911\",[469,67.731]],[\"comment/911\",[]],[\"name/912\",[470,64.366]],[\"comment/912\",[]],[\"name/913\",[471,64.366]],[\"comment/913\",[]],[\"name/914\",[472,64.366]],[\"comment/914\",[]],[\"name/915\",[473,64.366]],[\"comment/915\",[]],[\"name/916\",[153,43.05]],[\"comment/916\",[]],[\"name/917\",[475,72.839]],[\"comment/917\",[]],[\"name/918\",[40,47.716]],[\"comment/918\",[]],[\"name/919\",[476,72.839]],[\"comment/919\",[]],[\"name/920\",[51,33.521]],[\"comment/920\",[]],[\"name/921\",[4,64.366]],[\"comment/921\",[]],[\"name/922\",[71,67.731]],[\"comment/922\",[]],[\"name/923\",[477,59.846]],[\"comment/923\",[]],[\"name/924\",[478,59.846]],[\"comment/924\",[]],[\"name/925\",[479,59.846]],[\"comment/925\",[]],[\"name/926\",[480,59.846]],[\"comment/926\",[]],[\"name/927\",[481,59.846]],[\"comment/927\",[]],[\"name/928\",[482,59.846]],[\"comment/928\",[]],[\"name/929\",[60,56.745]],[\"comment/929\",[]],[\"name/930\",[483,72.839]],[\"comment/930\",[]],[\"name/931\",[484,67.731]],[\"comment/931\",[]],[\"name/932\",[485,72.839]],[\"comment/932\",[]],[\"name/933\",[484,67.731]],[\"comment/933\",[]],[\"name/934\",[486,72.839]],[\"comment/934\",[]],[\"name/935\",[62,58.176]],[\"comment/935\",[]],[\"name/936\",[487,72.839]],[\"comment/936\",[]],[\"name/937\",[488,72.839]],[\"comment/937\",[]],[\"name/938\",[489,72.839]],[\"comment/938\",[]],[\"name/939\",[490,72.839]],[\"comment/939\",[]],[\"name/940\",[219,64.366]],[\"comment/940\",[]],[\"name/941\",[491,67.731]],[\"comment/941\",[]],[\"name/942\",[492,72.839]],[\"comment/942\",[]],[\"name/943\",[279,58.176]],[\"comment/943\",[]],[\"name/944\",[493,72.839]],[\"comment/944\",[]],[\"name/945\",[51,33.521]],[\"comment/945\",[]],[\"name/946\",[279,58.176]],[\"comment/946\",[]],[\"name/947\",[494,72.839]],[\"comment/947\",[]],[\"name/948\",[51,33.521]],[\"comment/948\",[]],[\"name/949\",[279,58.176]],[\"comment/949\",[]],[\"name/950\",[495,72.839]],[\"comment/950\",[]],[\"name/951\",[51,33.521]],[\"comment/951\",[]],[\"name/952\",[477,59.846]],[\"comment/952\",[]],[\"name/953\",[478,59.846]],[\"comment/953\",[]],[\"name/954\",[479,59.846]],[\"comment/954\",[]],[\"name/955\",[480,59.846]],[\"comment/955\",[]],[\"name/956\",[481,59.846]],[\"comment/956\",[]],[\"name/957\",[482,59.846]],[\"comment/957\",[]],[\"name/958\",[60,56.745]],[\"comment/958\",[]],[\"name/959\",[73,64.366]],[\"comment/959\",[]],[\"name/960\",[496,61.853]],[\"comment/960\",[]],[\"name/961\",[497,61.853]],[\"comment/961\",[]],[\"name/962\",[498,61.853]],[\"comment/962\",[]],[\"name/963\",[499,61.853]],[\"comment/963\",[]],[\"name/964\",[500,72.839]],[\"comment/964\",[]],[\"name/965\",[501,59.846]],[\"comment/965\",[]],[\"name/966\",[502,59.846]],[\"comment/966\",[]],[\"name/967\",[503,59.846]],[\"comment/967\",[]],[\"name/968\",[504,59.846]],[\"comment/968\",[]],[\"name/969\",[505,72.839]],[\"comment/969\",[]],[\"name/970\",[506,72.839]],[\"comment/970\",[]],[\"name/971\",[507,72.839]],[\"comment/971\",[]],[\"name/972\",[508,72.839]],[\"comment/972\",[]],[\"name/973\",[509,72.839]],[\"comment/973\",[]],[\"name/974\",[51,33.521]],[\"comment/974\",[]],[\"name/975\",[501,59.846]],[\"comment/975\",[]],[\"name/976\",[502,59.846]],[\"comment/976\",[]],[\"name/977\",[503,59.846]],[\"comment/977\",[]],[\"name/978\",[504,59.846]],[\"comment/978\",[]],[\"name/979\",[510,72.839]],[\"comment/979\",[]],[\"name/980\",[511,61.853]],[\"comment/980\",[]],[\"name/981\",[512,61.853]],[\"comment/981\",[]],[\"name/982\",[513,61.853]],[\"comment/982\",[]],[\"name/983\",[514,72.839]],[\"comment/983\",[]],[\"name/984\",[515,72.839]],[\"comment/984\",[]],[\"name/985\",[516,72.839]],[\"comment/985\",[]],[\"name/986\",[517,48.86]],[\"comment/986\",[]],[\"name/987\",[518,72.839]],[\"comment/987\",[]],[\"name/988\",[519,67.731]],[\"comment/988\",[]],[\"name/989\",[520,72.839]],[\"comment/989\",[]],[\"name/990\",[517,48.86]],[\"comment/990\",[]],[\"name/991\",[521,72.839]],[\"comment/991\",[]],[\"name/992\",[172,49.485]],[\"comment/992\",[]],[\"name/993\",[52,59.846]],[\"comment/993\",[]],[\"name/994\",[522,72.839]],[\"comment/994\",[]],[\"name/995\",[517,48.86]],[\"comment/995\",[]],[\"name/996\",[523,61.853]],[\"comment/996\",[]],[\"name/997\",[524,72.839]],[\"comment/997\",[]],[\"name/998\",[525,72.839]],[\"comment/998\",[]],[\"name/999\",[526,72.839]],[\"comment/999\",[]],[\"name/1000\",[527,72.839]],[\"comment/1000\",[]],[\"name/1001\",[528,72.839]],[\"comment/1001\",[]],[\"name/1002\",[51,33.521]],[\"comment/1002\",[]],[\"name/1003\",[496,61.853]],[\"comment/1003\",[]],[\"name/1004\",[497,61.853]],[\"comment/1004\",[]],[\"name/1005\",[498,61.853]],[\"comment/1005\",[]],[\"name/1006\",[499,61.853]],[\"comment/1006\",[]],[\"name/1007\",[529,72.839]],[\"comment/1007\",[]],[\"name/1008\",[530,72.839]],[\"comment/1008\",[]],[\"name/1009\",[531,64.366]],[\"comment/1009\",[]],[\"name/1010\",[40,47.716]],[\"comment/1010\",[]],[\"name/1011\",[532,72.839]],[\"comment/1011\",[]],[\"name/1012\",[533,67.731]],[\"comment/1012\",[]],[\"name/1013\",[534,72.839]],[\"comment/1013\",[]],[\"name/1014\",[535,72.839]],[\"comment/1014\",[]],[\"name/1015\",[536,72.839]],[\"comment/1015\",[]],[\"name/1016\",[537,67.731]],[\"comment/1016\",[]],[\"name/1017\",[538,72.839]],[\"comment/1017\",[]],[\"name/1018\",[40,47.716]],[\"comment/1018\",[]],[\"name/1019\",[539,72.839]],[\"comment/1019\",[]],[\"name/1020\",[540,72.839]],[\"comment/1020\",[]],[\"name/1021\",[541,72.839]],[\"comment/1021\",[]],[\"name/1022\",[51,33.521]],[\"comment/1022\",[]],[\"name/1023\",[477,59.846]],[\"comment/1023\",[]],[\"name/1024\",[478,59.846]],[\"comment/1024\",[]],[\"name/1025\",[479,59.846]],[\"comment/1025\",[]],[\"name/1026\",[480,59.846]],[\"comment/1026\",[]],[\"name/1027\",[481,59.846]],[\"comment/1027\",[]],[\"name/1028\",[482,59.846]],[\"comment/1028\",[]],[\"name/1029\",[60,56.745]],[\"comment/1029\",[]],[\"name/1030\",[542,72.839]],[\"comment/1030\",[]],[\"name/1031\",[51,33.521]],[\"comment/1031\",[]],[\"name/1032\",[381,61.853]],[\"comment/1032\",[]],[\"name/1033\",[284,61.853]],[\"comment/1033\",[]],[\"name/1034\",[275,55.493]],[\"comment/1034\",[]],[\"name/1035\",[285,61.853]],[\"comment/1035\",[]],[\"name/1036\",[286,59.846]],[\"comment/1036\",[]],[\"name/1037\",[287,59.846]],[\"comment/1037\",[]],[\"name/1038\",[288,59.846]],[\"comment/1038\",[]],[\"name/1039\",[289,59.846]],[\"comment/1039\",[]],[\"name/1040\",[290,61.853]],[\"comment/1040\",[]],[\"name/1041\",[291,61.853]],[\"comment/1041\",[]],[\"name/1042\",[292,59.846]],[\"comment/1042\",[]],[\"name/1043\",[293,59.846]],[\"comment/1043\",[]],[\"name/1044\",[294,59.846]],[\"comment/1044\",[]],[\"name/1045\",[295,59.846]],[\"comment/1045\",[]],[\"name/1046\",[296,59.846]],[\"comment/1046\",[]],[\"name/1047\",[297,59.846]],[\"comment/1047\",[]],[\"name/1048\",[298,59.846]],[\"comment/1048\",[]],[\"name/1049\",[299,59.846]],[\"comment/1049\",[]],[\"name/1050\",[300,59.846]],[\"comment/1050\",[]],[\"name/1051\",[301,59.846]],[\"comment/1051\",[]],[\"name/1052\",[302,61.853]],[\"comment/1052\",[]],[\"name/1053\",[303,59.846]],[\"comment/1053\",[]],[\"name/1054\",[304,59.846]],[\"comment/1054\",[]],[\"name/1055\",[305,59.846]],[\"comment/1055\",[]],[\"name/1056\",[306,59.846]],[\"comment/1056\",[]],[\"name/1057\",[307,59.846]],[\"comment/1057\",[]],[\"name/1058\",[308,59.846]],[\"comment/1058\",[]],[\"name/1059\",[309,59.846]],[\"comment/1059\",[]],[\"name/1060\",[310,59.846]],[\"comment/1060\",[]],[\"name/1061\",[311,59.846]],[\"comment/1061\",[]],[\"name/1062\",[312,59.846]],[\"comment/1062\",[]],[\"name/1063\",[313,59.846]],[\"comment/1063\",[]],[\"name/1064\",[314,59.846]],[\"comment/1064\",[]],[\"name/1065\",[315,59.846]],[\"comment/1065\",[]],[\"name/1066\",[316,59.846]],[\"comment/1066\",[]],[\"name/1067\",[317,61.853]],[\"comment/1067\",[]],[\"name/1068\",[318,59.846]],[\"comment/1068\",[]],[\"name/1069\",[319,59.846]],[\"comment/1069\",[]],[\"name/1070\",[320,59.846]],[\"comment/1070\",[]],[\"name/1071\",[321,59.846]],[\"comment/1071\",[]],[\"name/1072\",[322,59.846]],[\"comment/1072\",[]],[\"name/1073\",[323,59.846]],[\"comment/1073\",[]],[\"name/1074\",[324,59.846]],[\"comment/1074\",[]],[\"name/1075\",[325,59.846]],[\"comment/1075\",[]],[\"name/1076\",[326,59.846]],[\"comment/1076\",[]],[\"name/1077\",[327,59.846]],[\"comment/1077\",[]],[\"name/1078\",[328,59.846]],[\"comment/1078\",[]],[\"name/1079\",[329,59.846]],[\"comment/1079\",[]],[\"name/1080\",[330,59.846]],[\"comment/1080\",[]],[\"name/1081\",[331,59.846]],[\"comment/1081\",[]],[\"name/1082\",[332,59.846]],[\"comment/1082\",[]],[\"name/1083\",[333,59.846]],[\"comment/1083\",[]],[\"name/1084\",[334,59.846]],[\"comment/1084\",[]],[\"name/1085\",[335,59.846]],[\"comment/1085\",[]],[\"name/1086\",[336,59.846]],[\"comment/1086\",[]],[\"name/1087\",[337,59.846]],[\"comment/1087\",[]],[\"name/1088\",[338,59.846]],[\"comment/1088\",[]],[\"name/1089\",[339,59.846]],[\"comment/1089\",[]],[\"name/1090\",[340,59.846]],[\"comment/1090\",[]],[\"name/1091\",[341,59.846]],[\"comment/1091\",[]],[\"name/1092\",[342,59.846]],[\"comment/1092\",[]],[\"name/1093\",[343,59.846]],[\"comment/1093\",[]],[\"name/1094\",[344,59.846]],[\"comment/1094\",[]],[\"name/1095\",[345,59.846]],[\"comment/1095\",[]],[\"name/1096\",[346,59.846]],[\"comment/1096\",[]],[\"name/1097\",[347,59.846]],[\"comment/1097\",[]],[\"name/1098\",[348,59.846]],[\"comment/1098\",[]],[\"name/1099\",[349,59.846]],[\"comment/1099\",[]],[\"name/1100\",[350,59.846]],[\"comment/1100\",[]],[\"name/1101\",[351,59.846]],[\"comment/1101\",[]],[\"name/1102\",[352,59.846]],[\"comment/1102\",[]],[\"name/1103\",[353,59.846]],[\"comment/1103\",[]],[\"name/1104\",[354,59.846]],[\"comment/1104\",[]],[\"name/1105\",[355,59.846]],[\"comment/1105\",[]],[\"name/1106\",[356,59.846]],[\"comment/1106\",[]],[\"name/1107\",[357,59.846]],[\"comment/1107\",[]],[\"name/1108\",[358,59.846]],[\"comment/1108\",[]],[\"name/1109\",[359,59.846]],[\"comment/1109\",[]],[\"name/1110\",[360,59.846]],[\"comment/1110\",[]],[\"name/1111\",[361,59.846]],[\"comment/1111\",[]],[\"name/1112\",[362,59.846]],[\"comment/1112\",[]],[\"name/1113\",[363,59.846]],[\"comment/1113\",[]],[\"name/1114\",[364,59.846]],[\"comment/1114\",[]],[\"name/1115\",[365,59.846]],[\"comment/1115\",[]],[\"name/1116\",[366,59.846]],[\"comment/1116\",[]],[\"name/1117\",[367,61.853]],[\"comment/1117\",[]],[\"name/1118\",[368,59.846]],[\"comment/1118\",[]],[\"name/1119\",[369,59.846]],[\"comment/1119\",[]],[\"name/1120\",[370,59.846]],[\"comment/1120\",[]],[\"name/1121\",[371,59.846]],[\"comment/1121\",[]],[\"name/1122\",[372,61.853]],[\"comment/1122\",[]],[\"name/1123\",[373,61.853]],[\"comment/1123\",[]],[\"name/1124\",[374,61.853]],[\"comment/1124\",[]],[\"name/1125\",[375,61.853]],[\"comment/1125\",[]],[\"name/1126\",[376,61.853]],[\"comment/1126\",[]],[\"name/1127\",[377,61.853]],[\"comment/1127\",[]],[\"name/1128\",[378,61.853]],[\"comment/1128\",[]],[\"name/1129\",[379,61.853]],[\"comment/1129\",[]],[\"name/1130\",[380,61.853]],[\"comment/1130\",[]],[\"name/1131\",[382,61.853]],[\"comment/1131\",[]],[\"name/1132\",[383,61.853]],[\"comment/1132\",[]],[\"name/1133\",[384,58.176]],[\"comment/1133\",[]],[\"name/1134\",[385,59.846]],[\"comment/1134\",[]],[\"name/1135\",[386,59.846]],[\"comment/1135\",[]],[\"name/1136\",[543,72.839]],[\"comment/1136\",[]],[\"name/1137\",[51,33.521]],[\"comment/1137\",[]],[\"name/1138\",[511,61.853]],[\"comment/1138\",[]],[\"name/1139\",[512,61.853]],[\"comment/1139\",[]],[\"name/1140\",[513,61.853]],[\"comment/1140\",[]],[\"name/1141\",[544,72.839]],[\"comment/1141\",[]],[\"name/1142\",[51,33.521]],[\"comment/1142\",[]],[\"name/1143\",[501,59.846]],[\"comment/1143\",[]],[\"name/1144\",[502,59.846]],[\"comment/1144\",[]],[\"name/1145\",[503,59.846]],[\"comment/1145\",[]],[\"name/1146\",[504,59.846]],[\"comment/1146\",[]],[\"name/1147\",[545,72.839]],[\"comment/1147\",[]],[\"name/1148\",[51,33.521]],[\"comment/1148\",[]],[\"name/1149\",[496,61.853]],[\"comment/1149\",[]],[\"name/1150\",[497,61.853]],[\"comment/1150\",[]],[\"name/1151\",[498,61.853]],[\"comment/1151\",[]],[\"name/1152\",[499,61.853]],[\"comment/1152\",[]],[\"name/1153\",[546,72.839]],[\"comment/1153\",[]],[\"name/1154\",[547,67.731]],[\"comment/1154\",[]],[\"name/1155\",[531,64.366]],[\"comment/1155\",[]],[\"name/1156\",[40,47.716]],[\"comment/1156\",[]],[\"name/1157\",[548,72.839]],[\"comment/1157\",[]],[\"name/1158\",[549,72.839]],[\"comment/1158\",[]],[\"name/1159\",[256,61.853]],[\"comment/1159\",[]],[\"name/1160\",[550,72.839]],[\"comment/1160\",[]],[\"name/1161\",[388,58.176]],[\"comment/1161\",[]],[\"name/1162\",[40,47.716]],[\"comment/1162\",[]],[\"name/1163\",[160,54.381]],[\"comment/1163\",[]],[\"name/1164\",[40,47.716]],[\"comment/1164\",[]],[\"name/1165\",[551,67.731]],[\"comment/1165\",[]],[\"name/1166\",[552,72.839]],[\"comment/1166\",[]],[\"name/1167\",[553,72.839]],[\"comment/1167\",[]],[\"name/1168\",[554,72.839]],[\"comment/1168\",[]],[\"name/1169\",[555,72.839]],[\"comment/1169\",[]],[\"name/1170\",[556,67.731]],[\"comment/1170\",[]],[\"name/1171\",[557,72.839]],[\"comment/1171\",[]],[\"name/1172\",[558,72.839]],[\"comment/1172\",[]],[\"name/1173\",[219,64.366]],[\"comment/1173\",[]],[\"name/1174\",[559,72.839]],[\"comment/1174\",[]],[\"name/1175\",[560,72.839]],[\"comment/1175\",[]],[\"name/1176\",[51,33.521]],[\"comment/1176\",[]],[\"name/1177\",[477,59.846]],[\"comment/1177\",[]],[\"name/1178\",[478,59.846]],[\"comment/1178\",[]],[\"name/1179\",[479,59.846]],[\"comment/1179\",[]],[\"name/1180\",[480,59.846]],[\"comment/1180\",[]],[\"name/1181\",[481,59.846]],[\"comment/1181\",[]],[\"name/1182\",[482,59.846]],[\"comment/1182\",[]],[\"name/1183\",[60,56.745]],[\"comment/1183\",[]],[\"name/1184\",[561,72.839]],[\"comment/1184\",[]],[\"name/1185\",[51,33.521]],[\"comment/1185\",[]],[\"name/1186\",[376,61.853]],[\"comment/1186\",[]],[\"name/1187\",[377,61.853]],[\"comment/1187\",[]],[\"name/1188\",[378,61.853]],[\"comment/1188\",[]],[\"name/1189\",[379,61.853]],[\"comment/1189\",[]],[\"name/1190\",[380,61.853]],[\"comment/1190\",[]],[\"name/1191\",[374,61.853]],[\"comment/1191\",[]],[\"name/1192\",[375,61.853]],[\"comment/1192\",[]],[\"name/1193\",[381,61.853]],[\"comment/1193\",[]],[\"name/1194\",[284,61.853]],[\"comment/1194\",[]],[\"name/1195\",[275,55.493]],[\"comment/1195\",[]],[\"name/1196\",[285,61.853]],[\"comment/1196\",[]],[\"name/1197\",[286,59.846]],[\"comment/1197\",[]],[\"name/1198\",[287,59.846]],[\"comment/1198\",[]],[\"name/1199\",[288,59.846]],[\"comment/1199\",[]],[\"name/1200\",[289,59.846]],[\"comment/1200\",[]],[\"name/1201\",[290,61.853]],[\"comment/1201\",[]],[\"name/1202\",[291,61.853]],[\"comment/1202\",[]],[\"name/1203\",[292,59.846]],[\"comment/1203\",[]],[\"name/1204\",[293,59.846]],[\"comment/1204\",[]],[\"name/1205\",[294,59.846]],[\"comment/1205\",[]],[\"name/1206\",[295,59.846]],[\"comment/1206\",[]],[\"name/1207\",[296,59.846]],[\"comment/1207\",[]],[\"name/1208\",[297,59.846]],[\"comment/1208\",[]],[\"name/1209\",[298,59.846]],[\"comment/1209\",[]],[\"name/1210\",[299,59.846]],[\"comment/1210\",[]],[\"name/1211\",[300,59.846]],[\"comment/1211\",[]],[\"name/1212\",[301,59.846]],[\"comment/1212\",[]],[\"name/1213\",[302,61.853]],[\"comment/1213\",[]],[\"name/1214\",[303,59.846]],[\"comment/1214\",[]],[\"name/1215\",[304,59.846]],[\"comment/1215\",[]],[\"name/1216\",[305,59.846]],[\"comment/1216\",[]],[\"name/1217\",[306,59.846]],[\"comment/1217\",[]],[\"name/1218\",[307,59.846]],[\"comment/1218\",[]],[\"name/1219\",[308,59.846]],[\"comment/1219\",[]],[\"name/1220\",[309,59.846]],[\"comment/1220\",[]],[\"name/1221\",[310,59.846]],[\"comment/1221\",[]],[\"name/1222\",[311,59.846]],[\"comment/1222\",[]],[\"name/1223\",[312,59.846]],[\"comment/1223\",[]],[\"name/1224\",[313,59.846]],[\"comment/1224\",[]],[\"name/1225\",[314,59.846]],[\"comment/1225\",[]],[\"name/1226\",[315,59.846]],[\"comment/1226\",[]],[\"name/1227\",[316,59.846]],[\"comment/1227\",[]],[\"name/1228\",[317,61.853]],[\"comment/1228\",[]],[\"name/1229\",[318,59.846]],[\"comment/1229\",[]],[\"name/1230\",[319,59.846]],[\"comment/1230\",[]],[\"name/1231\",[320,59.846]],[\"comment/1231\",[]],[\"name/1232\",[321,59.846]],[\"comment/1232\",[]],[\"name/1233\",[322,59.846]],[\"comment/1233\",[]],[\"name/1234\",[323,59.846]],[\"comment/1234\",[]],[\"name/1235\",[324,59.846]],[\"comment/1235\",[]],[\"name/1236\",[325,59.846]],[\"comment/1236\",[]],[\"name/1237\",[326,59.846]],[\"comment/1237\",[]],[\"name/1238\",[327,59.846]],[\"comment/1238\",[]],[\"name/1239\",[328,59.846]],[\"comment/1239\",[]],[\"name/1240\",[329,59.846]],[\"comment/1240\",[]],[\"name/1241\",[330,59.846]],[\"comment/1241\",[]],[\"name/1242\",[331,59.846]],[\"comment/1242\",[]],[\"name/1243\",[332,59.846]],[\"comment/1243\",[]],[\"name/1244\",[333,59.846]],[\"comment/1244\",[]],[\"name/1245\",[334,59.846]],[\"comment/1245\",[]],[\"name/1246\",[335,59.846]],[\"comment/1246\",[]],[\"name/1247\",[336,59.846]],[\"comment/1247\",[]],[\"name/1248\",[337,59.846]],[\"comment/1248\",[]],[\"name/1249\",[338,59.846]],[\"comment/1249\",[]],[\"name/1250\",[339,59.846]],[\"comment/1250\",[]],[\"name/1251\",[340,59.846]],[\"comment/1251\",[]],[\"name/1252\",[341,59.846]],[\"comment/1252\",[]],[\"name/1253\",[342,59.846]],[\"comment/1253\",[]],[\"name/1254\",[343,59.846]],[\"comment/1254\",[]],[\"name/1255\",[344,59.846]],[\"comment/1255\",[]],[\"name/1256\",[345,59.846]],[\"comment/1256\",[]],[\"name/1257\",[346,59.846]],[\"comment/1257\",[]],[\"name/1258\",[347,59.846]],[\"comment/1258\",[]],[\"name/1259\",[348,59.846]],[\"comment/1259\",[]],[\"name/1260\",[349,59.846]],[\"comment/1260\",[]],[\"name/1261\",[350,59.846]],[\"comment/1261\",[]],[\"name/1262\",[351,59.846]],[\"comment/1262\",[]],[\"name/1263\",[352,59.846]],[\"comment/1263\",[]],[\"name/1264\",[353,59.846]],[\"comment/1264\",[]],[\"name/1265\",[354,59.846]],[\"comment/1265\",[]],[\"name/1266\",[355,59.846]],[\"comment/1266\",[]],[\"name/1267\",[356,59.846]],[\"comment/1267\",[]],[\"name/1268\",[357,59.846]],[\"comment/1268\",[]],[\"name/1269\",[358,59.846]],[\"comment/1269\",[]],[\"name/1270\",[359,59.846]],[\"comment/1270\",[]],[\"name/1271\",[360,59.846]],[\"comment/1271\",[]],[\"name/1272\",[361,59.846]],[\"comment/1272\",[]],[\"name/1273\",[362,59.846]],[\"comment/1273\",[]],[\"name/1274\",[363,59.846]],[\"comment/1274\",[]],[\"name/1275\",[364,59.846]],[\"comment/1275\",[]],[\"name/1276\",[365,59.846]],[\"comment/1276\",[]],[\"name/1277\",[366,59.846]],[\"comment/1277\",[]],[\"name/1278\",[367,61.853]],[\"comment/1278\",[]],[\"name/1279\",[368,59.846]],[\"comment/1279\",[]],[\"name/1280\",[369,59.846]],[\"comment/1280\",[]],[\"name/1281\",[370,59.846]],[\"comment/1281\",[]],[\"name/1282\",[371,59.846]],[\"comment/1282\",[]],[\"name/1283\",[372,61.853]],[\"comment/1283\",[]],[\"name/1284\",[373,61.853]],[\"comment/1284\",[]],[\"name/1285\",[382,61.853]],[\"comment/1285\",[]],[\"name/1286\",[383,61.853]],[\"comment/1286\",[]],[\"name/1287\",[384,58.176]],[\"comment/1287\",[]],[\"name/1288\",[385,59.846]],[\"comment/1288\",[]],[\"name/1289\",[386,59.846]],[\"comment/1289\",[]],[\"name/1290\",[562,72.839]],[\"comment/1290\",[]],[\"name/1291\",[51,33.521]],[\"comment/1291\",[]],[\"name/1292\",[511,61.853]],[\"comment/1292\",[]],[\"name/1293\",[512,61.853]],[\"comment/1293\",[]],[\"name/1294\",[513,61.853]],[\"comment/1294\",[]],[\"name/1295\",[563,72.839]],[\"comment/1295\",[]],[\"name/1296\",[51,33.521]],[\"comment/1296\",[]],[\"name/1297\",[501,59.846]],[\"comment/1297\",[]],[\"name/1298\",[502,59.846]],[\"comment/1298\",[]],[\"name/1299\",[503,59.846]],[\"comment/1299\",[]],[\"name/1300\",[504,59.846]],[\"comment/1300\",[]],[\"name/1301\",[564,72.839]],[\"comment/1301\",[]],[\"name/1302\",[51,33.521]],[\"comment/1302\",[]],[\"name/1303\",[477,59.846]],[\"comment/1303\",[]],[\"name/1304\",[478,59.846]],[\"comment/1304\",[]],[\"name/1305\",[479,59.846]],[\"comment/1305\",[]],[\"name/1306\",[480,59.846]],[\"comment/1306\",[]],[\"name/1307\",[481,59.846]],[\"comment/1307\",[]],[\"name/1308\",[482,59.846]],[\"comment/1308\",[]],[\"name/1309\",[60,56.745]],[\"comment/1309\",[]],[\"name/1310\",[565,72.839]],[\"comment/1310\",[]],[\"name/1311\",[547,67.731]],[\"comment/1311\",[]],[\"name/1312\",[566,72.839]],[\"comment/1312\",[]],[\"name/1313\",[531,64.366]],[\"comment/1313\",[]],[\"name/1314\",[40,47.716]],[\"comment/1314\",[]],[\"name/1315\",[567,72.839]],[\"comment/1315\",[]],[\"name/1316\",[568,72.839]],[\"comment/1316\",[]],[\"name/1317\",[256,61.853]],[\"comment/1317\",[]],[\"name/1318\",[569,72.839]],[\"comment/1318\",[]],[\"name/1319\",[388,58.176]],[\"comment/1319\",[]],[\"name/1320\",[551,67.731]],[\"comment/1320\",[]],[\"name/1321\",[570,72.839]],[\"comment/1321\",[]],[\"name/1322\",[571,72.839]],[\"comment/1322\",[]],[\"name/1323\",[533,67.731]],[\"comment/1323\",[]],[\"name/1324\",[572,72.839]],[\"comment/1324\",[]],[\"name/1325\",[40,47.716]],[\"comment/1325\",[]],[\"name/1326\",[573,72.839]],[\"comment/1326\",[]],[\"name/1327\",[574,72.839]],[\"comment/1327\",[]],[\"name/1328\",[575,72.839]],[\"comment/1328\",[]],[\"name/1329\",[491,67.731]],[\"comment/1329\",[]],[\"name/1330\",[576,72.839]],[\"comment/1330\",[]],[\"name/1331\",[556,67.731]],[\"comment/1331\",[]],[\"name/1332\",[577,72.839]],[\"comment/1332\",[]],[\"name/1333\",[51,33.521]],[\"comment/1333\",[]],[\"name/1334\",[496,61.853]],[\"comment/1334\",[]],[\"name/1335\",[497,61.853]],[\"comment/1335\",[]],[\"name/1336\",[498,61.853]],[\"comment/1336\",[]],[\"name/1337\",[499,61.853]],[\"comment/1337\",[]],[\"name/1338\",[578,72.839]],[\"comment/1338\",[]],[\"name/1339\",[51,33.521]],[\"comment/1339\",[]],[\"name/1340\",[376,61.853]],[\"comment/1340\",[]],[\"name/1341\",[377,61.853]],[\"comment/1341\",[]],[\"name/1342\",[380,61.853]],[\"comment/1342\",[]],[\"name/1343\",[374,61.853]],[\"comment/1343\",[]],[\"name/1344\",[375,61.853]],[\"comment/1344\",[]],[\"name/1345\",[317,61.853]],[\"comment/1345\",[]],[\"name/1346\",[381,61.853]],[\"comment/1346\",[]],[\"name/1347\",[360,59.846]],[\"comment/1347\",[]],[\"name/1348\",[284,61.853]],[\"comment/1348\",[]],[\"name/1349\",[275,55.493]],[\"comment/1349\",[]],[\"name/1350\",[285,61.853]],[\"comment/1350\",[]],[\"name/1351\",[286,59.846]],[\"comment/1351\",[]],[\"name/1352\",[287,59.846]],[\"comment/1352\",[]],[\"name/1353\",[288,59.846]],[\"comment/1353\",[]],[\"name/1354\",[289,59.846]],[\"comment/1354\",[]],[\"name/1355\",[290,61.853]],[\"comment/1355\",[]],[\"name/1356\",[291,61.853]],[\"comment/1356\",[]],[\"name/1357\",[292,59.846]],[\"comment/1357\",[]],[\"name/1358\",[293,59.846]],[\"comment/1358\",[]],[\"name/1359\",[294,59.846]],[\"comment/1359\",[]],[\"name/1360\",[295,59.846]],[\"comment/1360\",[]],[\"name/1361\",[296,59.846]],[\"comment/1361\",[]],[\"name/1362\",[297,59.846]],[\"comment/1362\",[]],[\"name/1363\",[298,59.846]],[\"comment/1363\",[]],[\"name/1364\",[299,59.846]],[\"comment/1364\",[]],[\"name/1365\",[300,59.846]],[\"comment/1365\",[]],[\"name/1366\",[301,59.846]],[\"comment/1366\",[]],[\"name/1367\",[302,61.853]],[\"comment/1367\",[]],[\"name/1368\",[303,59.846]],[\"comment/1368\",[]],[\"name/1369\",[304,59.846]],[\"comment/1369\",[]],[\"name/1370\",[305,59.846]],[\"comment/1370\",[]],[\"name/1371\",[306,59.846]],[\"comment/1371\",[]],[\"name/1372\",[307,59.846]],[\"comment/1372\",[]],[\"name/1373\",[308,59.846]],[\"comment/1373\",[]],[\"name/1374\",[309,59.846]],[\"comment/1374\",[]],[\"name/1375\",[310,59.846]],[\"comment/1375\",[]],[\"name/1376\",[311,59.846]],[\"comment/1376\",[]],[\"name/1377\",[312,59.846]],[\"comment/1377\",[]],[\"name/1378\",[313,59.846]],[\"comment/1378\",[]],[\"name/1379\",[314,59.846]],[\"comment/1379\",[]],[\"name/1380\",[315,59.846]],[\"comment/1380\",[]],[\"name/1381\",[316,59.846]],[\"comment/1381\",[]],[\"name/1382\",[318,59.846]],[\"comment/1382\",[]],[\"name/1383\",[319,59.846]],[\"comment/1383\",[]],[\"name/1384\",[320,59.846]],[\"comment/1384\",[]],[\"name/1385\",[321,59.846]],[\"comment/1385\",[]],[\"name/1386\",[322,59.846]],[\"comment/1386\",[]],[\"name/1387\",[323,59.846]],[\"comment/1387\",[]],[\"name/1388\",[324,59.846]],[\"comment/1388\",[]],[\"name/1389\",[325,59.846]],[\"comment/1389\",[]],[\"name/1390\",[326,59.846]],[\"comment/1390\",[]],[\"name/1391\",[327,59.846]],[\"comment/1391\",[]],[\"name/1392\",[328,59.846]],[\"comment/1392\",[]],[\"name/1393\",[329,59.846]],[\"comment/1393\",[]],[\"name/1394\",[330,59.846]],[\"comment/1394\",[]],[\"name/1395\",[331,59.846]],[\"comment/1395\",[]],[\"name/1396\",[332,59.846]],[\"comment/1396\",[]],[\"name/1397\",[333,59.846]],[\"comment/1397\",[]],[\"name/1398\",[334,59.846]],[\"comment/1398\",[]],[\"name/1399\",[335,59.846]],[\"comment/1399\",[]],[\"name/1400\",[336,59.846]],[\"comment/1400\",[]],[\"name/1401\",[337,59.846]],[\"comment/1401\",[]],[\"name/1402\",[338,59.846]],[\"comment/1402\",[]],[\"name/1403\",[339,59.846]],[\"comment/1403\",[]],[\"name/1404\",[340,59.846]],[\"comment/1404\",[]],[\"name/1405\",[341,59.846]],[\"comment/1405\",[]],[\"name/1406\",[342,59.846]],[\"comment/1406\",[]],[\"name/1407\",[343,59.846]],[\"comment/1407\",[]],[\"name/1408\",[344,59.846]],[\"comment/1408\",[]],[\"name/1409\",[345,59.846]],[\"comment/1409\",[]],[\"name/1410\",[346,59.846]],[\"comment/1410\",[]],[\"name/1411\",[347,59.846]],[\"comment/1411\",[]],[\"name/1412\",[348,59.846]],[\"comment/1412\",[]],[\"name/1413\",[349,59.846]],[\"comment/1413\",[]],[\"name/1414\",[350,59.846]],[\"comment/1414\",[]],[\"name/1415\",[351,59.846]],[\"comment/1415\",[]],[\"name/1416\",[352,59.846]],[\"comment/1416\",[]],[\"name/1417\",[353,59.846]],[\"comment/1417\",[]],[\"name/1418\",[354,59.846]],[\"comment/1418\",[]],[\"name/1419\",[355,59.846]],[\"comment/1419\",[]],[\"name/1420\",[356,59.846]],[\"comment/1420\",[]],[\"name/1421\",[357,59.846]],[\"comment/1421\",[]],[\"name/1422\",[358,59.846]],[\"comment/1422\",[]],[\"name/1423\",[359,59.846]],[\"comment/1423\",[]],[\"name/1424\",[361,59.846]],[\"comment/1424\",[]],[\"name/1425\",[362,59.846]],[\"comment/1425\",[]],[\"name/1426\",[363,59.846]],[\"comment/1426\",[]],[\"name/1427\",[364,59.846]],[\"comment/1427\",[]],[\"name/1428\",[365,59.846]],[\"comment/1428\",[]],[\"name/1429\",[366,59.846]],[\"comment/1429\",[]],[\"name/1430\",[367,61.853]],[\"comment/1430\",[]],[\"name/1431\",[368,59.846]],[\"comment/1431\",[]],[\"name/1432\",[369,59.846]],[\"comment/1432\",[]],[\"name/1433\",[370,59.846]],[\"comment/1433\",[]],[\"name/1434\",[371,59.846]],[\"comment/1434\",[]],[\"name/1435\",[372,61.853]],[\"comment/1435\",[]],[\"name/1436\",[373,61.853]],[\"comment/1436\",[]],[\"name/1437\",[378,61.853]],[\"comment/1437\",[]],[\"name/1438\",[379,61.853]],[\"comment/1438\",[]],[\"name/1439\",[382,61.853]],[\"comment/1439\",[]],[\"name/1440\",[383,61.853]],[\"comment/1440\",[]],[\"name/1441\",[384,58.176]],[\"comment/1441\",[]],[\"name/1442\",[385,59.846]],[\"comment/1442\",[]],[\"name/1443\",[386,59.846]],[\"comment/1443\",[]],[\"name/1444\",[579,72.839]],[\"comment/1444\",[]],[\"name/1445\",[51,33.521]],[\"comment/1445\",[]],[\"name/1446\",[511,61.853]],[\"comment/1446\",[]],[\"name/1447\",[512,61.853]],[\"comment/1447\",[]],[\"name/1448\",[513,61.853]],[\"comment/1448\",[]],[\"name/1449\",[580,72.839]],[\"comment/1449\",[]],[\"name/1450\",[51,33.521]],[\"comment/1450\",[]],[\"name/1451\",[501,59.846]],[\"comment/1451\",[]],[\"name/1452\",[502,59.846]],[\"comment/1452\",[]],[\"name/1453\",[503,59.846]],[\"comment/1453\",[]],[\"name/1454\",[504,59.846]],[\"comment/1454\",[]],[\"name/1455\",[581,72.839]],[\"comment/1455\",[]],[\"name/1456\",[582,72.839]],[\"comment/1456\",[]],[\"name/1457\",[275,55.493]],[\"comment/1457\",[]],[\"name/1458\",[583,72.839]],[\"comment/1458\",[]],[\"name/1459\",[584,72.839]],[\"comment/1459\",[]],[\"name/1460\",[585,72.839]],[\"comment/1460\",[]],[\"name/1461\",[586,72.839]],[\"comment/1461\",[]],[\"name/1462\",[587,67.731]],[\"comment/1462\",[]],[\"name/1463\",[588,72.839]],[\"comment/1463\",[]],[\"name/1464\",[589,72.839]],[\"comment/1464\",[]],[\"name/1465\",[590,72.839]],[\"comment/1465\",[]],[\"name/1466\",[51,33.521]],[\"comment/1466\",[]],[\"name/1467\",[591,64.366]],[\"comment/1467\",[]],[\"name/1468\",[592,72.839]],[\"comment/1468\",[]],[\"name/1469\",[593,72.839]],[\"comment/1469\",[]],[\"name/1470\",[594,72.839]],[\"comment/1470\",[]],[\"name/1471\",[595,72.839]],[\"comment/1471\",[]],[\"name/1472\",[596,72.839]],[\"comment/1472\",[]],[\"name/1473\",[597,72.839]],[\"comment/1473\",[]],[\"name/1474\",[598,72.839]],[\"comment/1474\",[]],[\"name/1475\",[599,72.839]],[\"comment/1475\",[]],[\"name/1476\",[600,72.839]],[\"comment/1476\",[]],[\"name/1477\",[601,72.839]],[\"comment/1477\",[]],[\"name/1478\",[602,72.839]],[\"comment/1478\",[]],[\"name/1479\",[603,64.366]],[\"comment/1479\",[]],[\"name/1480\",[604,72.839]],[\"comment/1480\",[]],[\"name/1481\",[605,72.839]],[\"comment/1481\",[]],[\"name/1482\",[606,72.839]],[\"comment/1482\",[]],[\"name/1483\",[607,67.731]],[\"comment/1483\",[]],[\"name/1484\",[608,72.839]],[\"comment/1484\",[]],[\"name/1485\",[609,72.839]],[\"comment/1485\",[]],[\"name/1486\",[591,64.366]],[\"comment/1486\",[]],[\"name/1487\",[610,72.839]],[\"comment/1487\",[]],[\"name/1488\",[611,72.839]],[\"comment/1488\",[]],[\"name/1489\",[612,72.839]],[\"comment/1489\",[]],[\"name/1490\",[517,48.86]],[\"comment/1490\",[]],[\"name/1491\",[587,67.731]],[\"comment/1491\",[]],[\"name/1492\",[613,72.839]],[\"comment/1492\",[]],[\"name/1493\",[614,72.839]],[\"comment/1493\",[]],[\"name/1494\",[51,33.521]],[\"comment/1494\",[]],[\"name/1495\",[591,64.366]],[\"comment/1495\",[]],[\"name/1496\",[615,72.839]],[\"comment/1496\",[]],[\"name/1497\",[616,72.839]],[\"comment/1497\",[]],[\"name/1498\",[617,72.839]],[\"comment/1498\",[]],[\"name/1499\",[271,67.731]],[\"comment/1499\",[]],[\"name/1500\",[618,72.839]],[\"comment/1500\",[]],[\"name/1501\",[619,72.839]],[\"comment/1501\",[]],[\"name/1502\",[620,72.839]],[\"comment/1502\",[]],[\"name/1503\",[621,72.839]],[\"comment/1503\",[]],[\"name/1504\",[622,72.839]],[\"comment/1504\",[]],[\"name/1505\",[274,56.745]],[\"comment/1505\",[]],[\"name/1506\",[623,61.853]],[\"comment/1506\",[]],[\"name/1507\",[624,72.839]],[\"comment/1507\",[]],[\"name/1508\",[163,47.19]],[\"comment/1508\",[]],[\"name/1509\",[195,48.86]],[\"comment/1509\",[]],[\"name/1510\",[625,72.839]],[\"comment/1510\",[]],[\"name/1511\",[163,47.19]],[\"comment/1511\",[]],[\"name/1512\",[626,67.731]],[\"comment/1512\",[]],[\"name/1513\",[627,72.839]],[\"comment/1513\",[]],[\"name/1514\",[628,72.839]],[\"comment/1514\",[]],[\"name/1515\",[629,72.839]],[\"comment/1515\",[]],[\"name/1516\",[630,72.839]],[\"comment/1516\",[]],[\"name/1517\",[631,72.839]],[\"comment/1517\",[]],[\"name/1518\",[632,72.839]],[\"comment/1518\",[]],[\"name/1519\",[51,33.521]],[\"comment/1519\",[]],[\"name/1520\",[633,72.839]],[\"comment/1520\",[]],[\"name/1521\",[274,56.745]],[\"comment/1521\",[]],[\"name/1522\",[623,61.853]],[\"comment/1522\",[]],[\"name/1523\",[634,72.839]],[\"comment/1523\",[]],[\"name/1524\",[635,72.839]],[\"comment/1524\",[]],[\"name/1525\",[636,72.839]],[\"comment/1525\",[]],[\"name/1526\",[637,72.839]],[\"comment/1526\",[]],[\"name/1527\",[51,33.521]],[\"comment/1527\",[]],[\"name/1528\",[274,56.745]],[\"comment/1528\",[]],[\"name/1529\",[623,61.853]],[\"comment/1529\",[]],[\"name/1530\",[638,72.839]],[\"comment/1530\",[]],[\"name/1531\",[51,33.521]],[\"comment/1531\",[]],[\"name/1532\",[274,56.745]],[\"comment/1532\",[]],[\"name/1533\",[623,61.853]],[\"comment/1533\",[]],[\"name/1534\",[639,72.839]],[\"comment/1534\",[]],[\"name/1535\",[640,33.136]],[\"comment/1535\",[]],[\"name/1536\",[226,52.47]],[\"comment/1536\",[]],[\"name/1537\",[641,72.839]],[\"comment/1537\",[]],[\"name/1538\",[640,33.136]],[\"comment/1538\",[]],[\"name/1539\",[227,64.366]],[\"comment/1539\",[]],[\"name/1540\",[642,72.839]],[\"comment/1540\",[]],[\"name/1541\",[640,33.136]],[\"comment/1541\",[]],[\"name/1542\",[195,48.86]],[\"comment/1542\",[]],[\"name/1543\",[90,67.731]],[\"comment/1543\",[]],[\"name/1544\",[643,72.839]],[\"comment/1544\",[]],[\"name/1545\",[468,64.366]],[\"comment/1545\",[]],[\"name/1546\",[640,33.136]],[\"comment/1546\",[]],[\"name/1547\",[226,52.47]],[\"comment/1547\",[]],[\"name/1548\",[523,61.853]],[\"comment/1548\",[]],[\"name/1549\",[644,72.839]],[\"comment/1549\",[]],[\"name/1550\",[470,64.366]],[\"comment/1550\",[]],[\"name/1551\",[471,64.366]],[\"comment/1551\",[]],[\"name/1552\",[472,64.366]],[\"comment/1552\",[]],[\"name/1553\",[473,64.366]],[\"comment/1553\",[]],[\"name/1554\",[645,72.839]],[\"comment/1554\",[]],[\"name/1555\",[646,72.839]],[\"comment/1555\",[]],[\"name/1556\",[647,72.839]],[\"comment/1556\",[]],[\"name/1557\",[640,33.136]],[\"comment/1557\",[]],[\"name/1558\",[266,51.636]],[\"comment/1558\",[]],[\"name/1559\",[450,64.366]],[\"comment/1559\",[]],[\"name/1560\",[451,67.731]],[\"comment/1560\",[]],[\"name/1561\",[648,72.839]],[\"comment/1561\",[]],[\"name/1562\",[649,72.839]],[\"comment/1562\",[]],[\"name/1563\",[456,67.731]],[\"comment/1563\",[]],[\"name/1564\",[650,72.839]],[\"comment/1564\",[]],[\"name/1565\",[640,33.136]],[\"comment/1565\",[]],[\"name/1566\",[651,67.731]],[\"comment/1566\",[]],[\"name/1567\",[652,67.731]],[\"comment/1567\",[]],[\"name/1568\",[653,72.839]],[\"comment/1568\",[]],[\"name/1569\",[640,33.136]],[\"comment/1569\",[]],[\"name/1570\",[265,61.853]],[\"comment/1570\",[]],[\"name/1571\",[251,64.366]],[\"comment/1571\",[]],[\"name/1572\",[255,67.731]],[\"comment/1572\",[]],[\"name/1573\",[654,72.839]],[\"comment/1573\",[]],[\"name/1574\",[655,72.839]],[\"comment/1574\",[]],[\"name/1575\",[640,33.136]],[\"comment/1575\",[]],[\"name/1576\",[86,54.381]],[\"comment/1576\",[]],[\"name/1577\",[517,48.86]],[\"comment/1577\",[]],[\"name/1578\",[656,72.839]],[\"comment/1578\",[]],[\"name/1579\",[657,72.839]],[\"comment/1579\",[]],[\"name/1580\",[640,33.136]],[\"comment/1580\",[]],[\"name/1581\",[226,52.47]],[\"comment/1581\",[]],[\"name/1582\",[523,61.853]],[\"comment/1582\",[]],[\"name/1583\",[435,64.366]],[\"comment/1583\",[]],[\"name/1584\",[434,67.731]],[\"comment/1584\",[]],[\"name/1585\",[433,67.731]],[\"comment/1585\",[]],[\"name/1586\",[424,61.853]],[\"comment/1586\",[]],[\"name/1587\",[438,67.731]],[\"comment/1587\",[]],[\"name/1588\",[440,67.731]],[\"comment/1588\",[]],[\"name/1589\",[441,67.731]],[\"comment/1589\",[]],[\"name/1590\",[658,67.731]],[\"comment/1590\",[]],[\"name/1591\",[439,67.731]],[\"comment/1591\",[]],[\"name/1592\",[659,64.366]],[\"comment/1592\",[]],[\"name/1593\",[660,64.366]],[\"comment/1593\",[]],[\"name/1594\",[661,72.839]],[\"comment/1594\",[]],[\"name/1595\",[640,33.136]],[\"comment/1595\",[]],[\"name/1596\",[226,52.47]],[\"comment/1596\",[]],[\"name/1597\",[662,72.839]],[\"comment/1597\",[]],[\"name/1598\",[640,33.136]],[\"comment/1598\",[]],[\"name/1599\",[226,52.47]],[\"comment/1599\",[]],[\"name/1600\",[265,61.853]],[\"comment/1600\",[]],[\"name/1601\",[663,72.839]],[\"comment/1601\",[]],[\"name/1602\",[640,33.136]],[\"comment/1602\",[]],[\"name/1603\",[517,48.86]],[\"comment/1603\",[]],[\"name/1604\",[86,54.381]],[\"comment/1604\",[]],[\"name/1605\",[664,72.839]],[\"comment/1605\",[]],[\"name/1606\",[640,33.136]],[\"comment/1606\",[]],[\"name/1607\",[266,51.636]],[\"comment/1607\",[]],[\"name/1608\",[172,49.485]],[\"comment/1608\",[]],[\"name/1609\",[665,72.839]],[\"comment/1609\",[]],[\"name/1610\",[666,72.839]],[\"comment/1610\",[]],[\"name/1611\",[667,72.839]],[\"comment/1611\",[]],[\"name/1612\",[668,72.839]],[\"comment/1612\",[]],[\"name/1613\",[640,33.136]],[\"comment/1613\",[]],[\"name/1614\",[517,48.86]],[\"comment/1614\",[]],[\"name/1615\",[266,51.636]],[\"comment/1615\",[]],[\"name/1616\",[172,49.485]],[\"comment/1616\",[]],[\"name/1617\",[424,61.853]],[\"comment/1617\",[]],[\"name/1618\",[186,61.853]],[\"comment/1618\",[]],[\"name/1619\",[405,55.493]],[\"comment/1619\",[]],[\"name/1620\",[96,51.636]],[\"comment/1620\",[]],[\"name/1621\",[669,72.839]],[\"comment/1621\",[]],[\"name/1622\",[670,72.839]],[\"comment/1622\",[]],[\"name/1623\",[640,33.136]],[\"comment/1623\",[]],[\"name/1624\",[52,59.846]],[\"comment/1624\",[]],[\"name/1625\",[405,55.493]],[\"comment/1625\",[]],[\"name/1626\",[671,72.839]],[\"comment/1626\",[]],[\"name/1627\",[672,72.839]],[\"comment/1627\",[]],[\"name/1628\",[673,72.839]],[\"comment/1628\",[]],[\"name/1629\",[674,72.839]],[\"comment/1629\",[]],[\"name/1630\",[640,33.136]],[\"comment/1630\",[]],[\"name/1631\",[266,51.636]],[\"comment/1631\",[]],[\"name/1632\",[172,49.485]],[\"comment/1632\",[]],[\"name/1633\",[675,72.839]],[\"comment/1633\",[]],[\"name/1634\",[403,61.853]],[\"comment/1634\",[]],[\"name/1635\",[405,55.493]],[\"comment/1635\",[]],[\"name/1636\",[404,67.731]],[\"comment/1636\",[]],[\"name/1637\",[659,64.366]],[\"comment/1637\",[]],[\"name/1638\",[660,64.366]],[\"comment/1638\",[]],[\"name/1639\",[676,72.839]],[\"comment/1639\",[]],[\"name/1640\",[677,72.839]],[\"comment/1640\",[]],[\"name/1641\",[640,33.136]],[\"comment/1641\",[]],[\"name/1642\",[517,48.86]],[\"comment/1642\",[]],[\"name/1643\",[678,72.839]],[\"comment/1643\",[]],[\"name/1644\",[679,72.839]],[\"comment/1644\",[]],[\"name/1645\",[680,72.839]],[\"comment/1645\",[]],[\"name/1646\",[640,33.136]],[\"comment/1646\",[]],[\"name/1647\",[517,48.86]],[\"comment/1647\",[]],[\"name/1648\",[403,61.853]],[\"comment/1648\",[]],[\"name/1649\",[462,61.853]],[\"comment/1649\",[]],[\"name/1650\",[463,67.731]],[\"comment/1650\",[]],[\"name/1651\",[405,55.493]],[\"comment/1651\",[]],[\"name/1652\",[172,49.485]],[\"comment/1652\",[]],[\"name/1653\",[92,58.176]],[\"comment/1653\",[]],[\"name/1654\",[681,72.839]],[\"comment/1654\",[]],[\"name/1655\",[682,72.839]],[\"comment/1655\",[]],[\"name/1656\",[683,72.839]],[\"comment/1656\",[]],[\"name/1657\",[640,33.136]],[\"comment/1657\",[]],[\"name/1658\",[523,61.853]],[\"comment/1658\",[]],[\"name/1659\",[684,72.839]],[\"comment/1659\",[]],[\"name/1660\",[640,33.136]],[\"comment/1660\",[]],[\"name/1661\",[685,72.839]],[\"comment/1661\",[]],[\"name/1662\",[686,72.839]],[\"comment/1662\",[]],[\"name/1663\",[640,33.136]],[\"comment/1663\",[]],[\"name/1664\",[178,61.853]],[\"comment/1664\",[]],[\"name/1665\",[186,61.853]],[\"comment/1665\",[]],[\"name/1666\",[687,64.366]],[\"comment/1666\",[]],[\"name/1667\",[96,51.636]],[\"comment/1667\",[]],[\"name/1668\",[107,56.745]],[\"comment/1668\",[]],[\"name/1669\",[67,56.745]],[\"comment/1669\",[]],[\"name/1670\",[139,58.176]],[\"comment/1670\",[]],[\"name/1671\",[141,59.846]],[\"comment/1671\",[]],[\"name/1672\",[161,54.381]],[\"comment/1672\",[]],[\"name/1673\",[688,72.839]],[\"comment/1673\",[]],[\"name/1674\",[640,33.136]],[\"comment/1674\",[]],[\"name/1675\",[226,52.47]],[\"comment/1675\",[]],[\"name/1676\",[689,72.839]],[\"comment/1676\",[]],[\"name/1677\",[690,72.839]],[\"comment/1677\",[]],[\"name/1678\",[640,33.136]],[\"comment/1678\",[]],[\"name/1679\",[691,72.839]],[\"comment/1679\",[]],[\"name/1680\",[418,52.47]],[\"comment/1680\",[]],[\"name/1681\",[692,72.839]],[\"comment/1681\",[]],[\"name/1682\",[693,72.839]],[\"comment/1682\",[]],[\"name/1683\",[694,72.839]],[\"comment/1683\",[]],[\"name/1684\",[640,33.136]],[\"comment/1684\",[]],[\"name/1685\",[517,48.86]],[\"comment/1685\",[]],[\"name/1686\",[266,51.636]],[\"comment/1686\",[]],[\"name/1687\",[418,52.47]],[\"comment/1687\",[]],[\"name/1688\",[419,55.493]],[\"comment/1688\",[]],[\"name/1689\",[695,72.839]],[\"comment/1689\",[]],[\"name/1690\",[696,72.839]],[\"comment/1690\",[]],[\"name/1691\",[640,33.136]],[\"comment/1691\",[]],[\"name/1692\",[52,59.846]],[\"comment/1692\",[]],[\"name/1693\",[418,52.47]],[\"comment/1693\",[]],[\"name/1694\",[419,55.493]],[\"comment/1694\",[]],[\"name/1695\",[697,72.839]],[\"comment/1695\",[]],[\"name/1696\",[698,72.839]],[\"comment/1696\",[]],[\"name/1697\",[640,33.136]],[\"comment/1697\",[]],[\"name/1698\",[266,51.636]],[\"comment/1698\",[]],[\"name/1699\",[418,52.47]],[\"comment/1699\",[]],[\"name/1700\",[419,55.493]],[\"comment/1700\",[]],[\"name/1701\",[699,72.839]],[\"comment/1701\",[]],[\"name/1702\",[700,72.839]],[\"comment/1702\",[]],[\"name/1703\",[640,33.136]],[\"comment/1703\",[]],[\"name/1704\",[517,48.86]],[\"comment/1704\",[]],[\"name/1705\",[418,52.47]],[\"comment/1705\",[]],[\"name/1706\",[701,72.839]],[\"comment/1706\",[]],[\"name/1707\",[702,72.839]],[\"comment/1707\",[]],[\"name/1708\",[640,33.136]],[\"comment/1708\",[]],[\"name/1709\",[517,48.86]],[\"comment/1709\",[]],[\"name/1710\",[418,52.47]],[\"comment/1710\",[]],[\"name/1711\",[462,61.853]],[\"comment/1711\",[]],[\"name/1712\",[419,55.493]],[\"comment/1712\",[]],[\"name/1713\",[703,72.839]],[\"comment/1713\",[]],[\"name/1714\",[704,72.839]],[\"comment/1714\",[]],[\"name/1715\",[640,33.136]],[\"comment/1715\",[]],[\"name/1716\",[172,49.485]],[\"comment/1716\",[]],[\"name/1717\",[435,64.366]],[\"comment/1717\",[]],[\"name/1718\",[436,59.846]],[\"comment/1718\",[]],[\"name/1719\",[437,59.846]],[\"comment/1719\",[]],[\"name/1720\",[517,48.86]],[\"comment/1720\",[]],[\"name/1721\",[705,72.839]],[\"comment/1721\",[]],[\"name/1722\",[640,33.136]],[\"comment/1722\",[]],[\"name/1723\",[706,72.839]],[\"comment/1723\",[]],[\"name/1724\",[707,72.839]],[\"comment/1724\",[]],[\"name/1725\",[708,72.839]],[\"comment/1725\",[]],[\"name/1726\",[640,33.136]],[\"comment/1726\",[]],[\"name/1727\",[709,72.839]],[\"comment/1727\",[]],[\"name/1728\",[710,72.839]],[\"comment/1728\",[]],[\"name/1729\",[711,72.839]],[\"comment/1729\",[]],[\"name/1730\",[445,67.731]],[\"comment/1730\",[]],[\"name/1731\",[86,54.381]],[\"comment/1731\",[]],[\"name/1732\",[712,72.839]],[\"comment/1732\",[]],[\"name/1733\",[640,33.136]],[\"comment/1733\",[]],[\"name/1734\",[140,64.366]],[\"comment/1734\",[]],[\"name/1735\",[713,72.839]],[\"comment/1735\",[]],[\"name/1736\",[640,33.136]],[\"comment/1736\",[]],[\"name/1737\",[714,61.853]],[\"comment/1737\",[]],[\"name/1738\",[715,72.839]],[\"comment/1738\",[]],[\"name/1739\",[640,33.136]],[\"comment/1739\",[]],[\"name/1740\",[110,61.853]],[\"comment/1740\",[]],[\"name/1741\",[716,72.839]],[\"comment/1741\",[]],[\"name/1742\",[640,33.136]],[\"comment/1742\",[]],[\"name/1743\",[517,48.86]],[\"comment/1743\",[]],[\"name/1744\",[717,72.839]],[\"comment/1744\",[]],[\"name/1745\",[718,72.839]],[\"comment/1745\",[]],[\"name/1746\",[640,33.136]],[\"comment/1746\",[]],[\"name/1747\",[719,72.839]],[\"comment/1747\",[]],[\"name/1748\",[172,49.485]],[\"comment/1748\",[]],[\"name/1749\",[171,59.846]],[\"comment/1749\",[]],[\"name/1750\",[107,56.745]],[\"comment/1750\",[]],[\"name/1751\",[174,67.731]],[\"comment/1751\",[]],[\"name/1752\",[720,72.839]],[\"comment/1752\",[]],[\"name/1753\",[67,56.745]],[\"comment/1753\",[]],[\"name/1754\",[173,67.731]],[\"comment/1754\",[]],[\"name/1755\",[721,72.839]],[\"comment/1755\",[]],[\"name/1756\",[161,54.381]],[\"comment/1756\",[]],[\"name/1757\",[722,67.731]],[\"comment/1757\",[]],[\"name/1758\",[207,67.731]],[\"comment/1758\",[]],[\"name/1759\",[640,33.136]],[\"comment/1759\",[]],[\"name/1760\",[722,67.731]],[\"comment/1760\",[]],[\"name/1761\",[266,51.636]],[\"comment/1761\",[]],[\"name/1762\",[197,59.846]],[\"comment/1762\",[]],[\"name/1763\",[723,72.839]],[\"comment/1763\",[]],[\"name/1764\",[640,33.136]],[\"comment/1764\",[]],[\"name/1765\",[141,59.846]],[\"comment/1765\",[]],[\"name/1766\",[724,72.839]],[\"comment/1766\",[]],[\"name/1767\",[640,33.136]],[\"comment/1767\",[]],[\"name/1768\",[714,61.853]],[\"comment/1768\",[]],[\"name/1769\",[725,72.839]],[\"comment/1769\",[]],[\"name/1770\",[640,33.136]],[\"comment/1770\",[]],[\"name/1771\",[226,52.47]],[\"comment/1771\",[]],[\"name/1772\",[726,72.839]],[\"comment/1772\",[]],[\"name/1773\",[640,33.136]],[\"comment/1773\",[]],[\"name/1774\",[142,64.366]],[\"comment/1774\",[]],[\"name/1775\",[727,72.839]],[\"comment/1775\",[]],[\"name/1776\",[231,67.731]],[\"comment/1776\",[]],[\"name/1777\",[640,33.136]],[\"comment/1777\",[]],[\"name/1778\",[172,49.485]],[\"comment/1778\",[]],[\"name/1779\",[227,64.366]],[\"comment/1779\",[]],[\"name/1780\",[728,72.839]],[\"comment/1780\",[]],[\"name/1781\",[729,72.839]],[\"comment/1781\",[]],[\"name/1782\",[730,64.366]],[\"comment/1782\",[]],[\"name/1783\",[731,72.839]],[\"comment/1783\",[]],[\"name/1784\",[228,67.731]],[\"comment/1784\",[]],[\"name/1785\",[732,72.839]],[\"comment/1785\",[]],[\"name/1786\",[733,72.839]],[\"comment/1786\",[]],[\"name/1787\",[640,33.136]],[\"comment/1787\",[]],[\"name/1788\",[730,64.366]],[\"comment/1788\",[]],[\"name/1789\",[734,72.839]],[\"comment/1789\",[]],[\"name/1790\",[640,33.136]],[\"comment/1790\",[]],[\"name/1791\",[197,59.846]],[\"comment/1791\",[]],[\"name/1792\",[735,72.839]],[\"comment/1792\",[]],[\"name/1793\",[736,72.839]],[\"comment/1793\",[]],[\"name/1794\",[88,42.394]],[\"comment/1794\",[]],[\"name/1795\",[737,72.839]],[\"comment/1795\",[]],[\"name/1796\",[51,33.521]],[\"comment/1796\",[]],[\"name/1797\",[384,58.176]],[\"comment/1797\",[]],[\"name/1798\",[738,72.839]],[\"comment/1798\",[]],[\"name/1799\",[739,72.839]],[\"comment/1799\",[]],[\"name/1800\",[740,72.839]],[\"comment/1800\",[]],[\"name/1801\",[741,72.839]],[\"comment/1801\",[]],[\"name/1802\",[742,72.839]],[\"comment/1802\",[]],[\"name/1803\",[743,72.839]],[\"comment/1803\",[]],[\"name/1804\",[744,72.839]],[\"comment/1804\",[]],[\"name/1805\",[745,72.839]],[\"comment/1805\",[]],[\"name/1806\",[746,72.839]],[\"comment/1806\",[]],[\"name/1807\",[747,72.839]],[\"comment/1807\",[]],[\"name/1808\",[748,72.839]],[\"comment/1808\",[]],[\"name/1809\",[749,72.839]],[\"comment/1809\",[]],[\"name/1810\",[750,72.839]],[\"comment/1810\",[]],[\"name/1811\",[751,72.839]],[\"comment/1811\",[]],[\"name/1812\",[752,72.839]],[\"comment/1812\",[]],[\"name/1813\",[753,72.839]],[\"comment/1813\",[]],[\"name/1814\",[754,72.839]],[\"comment/1814\",[]],[\"name/1815\",[755,72.839]],[\"comment/1815\",[]],[\"name/1816\",[756,72.839]],[\"comment/1816\",[]],[\"name/1817\",[757,72.839]],[\"comment/1817\",[]],[\"name/1818\",[758,72.839]],[\"comment/1818\",[]],[\"name/1819\",[759,72.839]],[\"comment/1819\",[]],[\"name/1820\",[760,72.839]],[\"comment/1820\",[]],[\"name/1821\",[761,72.839]],[\"comment/1821\",[]],[\"name/1822\",[762,72.839]],[\"comment/1822\",[]],[\"name/1823\",[763,72.839]],[\"comment/1823\",[]],[\"name/1824\",[764,72.839]],[\"comment/1824\",[]],[\"name/1825\",[765,72.839]],[\"comment/1825\",[]],[\"name/1826\",[766,72.839]],[\"comment/1826\",[]],[\"name/1827\",[767,72.839]],[\"comment/1827\",[]],[\"name/1828\",[768,72.839]],[\"comment/1828\",[]],[\"name/1829\",[769,72.839]],[\"comment/1829\",[]],[\"name/1830\",[770,72.839]],[\"comment/1830\",[]],[\"name/1831\",[771,72.839]],[\"comment/1831\",[]],[\"name/1832\",[772,72.839]],[\"comment/1832\",[]],[\"name/1833\",[773,72.839]],[\"comment/1833\",[]],[\"name/1834\",[774,72.839]],[\"comment/1834\",[]],[\"name/1835\",[775,72.839]],[\"comment/1835\",[]],[\"name/1836\",[776,72.839]],[\"comment/1836\",[]],[\"name/1837\",[777,72.839]],[\"comment/1837\",[]],[\"name/1838\",[778,72.839]],[\"comment/1838\",[]],[\"name/1839\",[779,72.839]],[\"comment/1839\",[]],[\"name/1840\",[780,72.839]],[\"comment/1840\",[]],[\"name/1841\",[781,72.839]],[\"comment/1841\",[]],[\"name/1842\",[782,72.839]],[\"comment/1842\",[]],[\"name/1843\",[783,72.839]],[\"comment/1843\",[]],[\"name/1844\",[784,72.839]],[\"comment/1844\",[]],[\"name/1845\",[785,72.839]],[\"comment/1845\",[]],[\"name/1846\",[786,72.839]],[\"comment/1846\",[]],[\"name/1847\",[787,72.839]],[\"comment/1847\",[]],[\"name/1848\",[788,72.839]],[\"comment/1848\",[]],[\"name/1849\",[789,72.839]],[\"comment/1849\",[]],[\"name/1850\",[790,72.839]],[\"comment/1850\",[]],[\"name/1851\",[791,72.839]],[\"comment/1851\",[]],[\"name/1852\",[792,72.839]],[\"comment/1852\",[]],[\"name/1853\",[793,72.839]],[\"comment/1853\",[]],[\"name/1854\",[794,72.839]],[\"comment/1854\",[]],[\"name/1855\",[795,72.839]],[\"comment/1855\",[]],[\"name/1856\",[796,72.839]],[\"comment/1856\",[]],[\"name/1857\",[797,72.839]],[\"comment/1857\",[]],[\"name/1858\",[798,72.839]],[\"comment/1858\",[]],[\"name/1859\",[799,72.839]],[\"comment/1859\",[]],[\"name/1860\",[800,72.839]],[\"comment/1860\",[]],[\"name/1861\",[801,72.839]],[\"comment/1861\",[]],[\"name/1862\",[802,72.839]],[\"comment/1862\",[]],[\"name/1863\",[803,72.839]],[\"comment/1863\",[]],[\"name/1864\",[804,72.839]],[\"comment/1864\",[]],[\"name/1865\",[805,72.839]],[\"comment/1865\",[]],[\"name/1866\",[806,72.839]],[\"comment/1866\",[]],[\"name/1867\",[807,72.839]],[\"comment/1867\",[]],[\"name/1868\",[808,72.839]],[\"comment/1868\",[]],[\"name/1869\",[809,72.839]],[\"comment/1869\",[]],[\"name/1870\",[810,72.839]],[\"comment/1870\",[]],[\"name/1871\",[811,72.839]],[\"comment/1871\",[]],[\"name/1872\",[812,72.839]],[\"comment/1872\",[]],[\"name/1873\",[813,72.839]],[\"comment/1873\",[]],[\"name/1874\",[814,72.839]],[\"comment/1874\",[]],[\"name/1875\",[815,72.839]],[\"comment/1875\",[]],[\"name/1876\",[816,72.839]],[\"comment/1876\",[]],[\"name/1877\",[817,72.839]],[\"comment/1877\",[]],[\"name/1878\",[818,72.839]],[\"comment/1878\",[]],[\"name/1879\",[819,72.839]],[\"comment/1879\",[]],[\"name/1880\",[820,72.839]],[\"comment/1880\",[]],[\"name/1881\",[821,72.839]],[\"comment/1881\",[]],[\"name/1882\",[822,72.839]],[\"comment/1882\",[]],[\"name/1883\",[51,33.521]],[\"comment/1883\",[]],[\"name/1884\",[384,58.176]],[\"comment/1884\",[]],[\"name/1885\",[385,59.846]],[\"comment/1885\",[]],[\"name/1886\",[386,59.846]],[\"comment/1886\",[]],[\"name/1887\",[286,59.846]],[\"comment/1887\",[]],[\"name/1888\",[288,59.846]],[\"comment/1888\",[]],[\"name/1889\",[289,59.846]],[\"comment/1889\",[]],[\"name/1890\",[298,59.846]],[\"comment/1890\",[]],[\"name/1891\",[313,59.846]],[\"comment/1891\",[]],[\"name/1892\",[287,59.846]],[\"comment/1892\",[]],[\"name/1893\",[299,59.846]],[\"comment/1893\",[]],[\"name/1894\",[303,59.846]],[\"comment/1894\",[]],[\"name/1895\",[304,59.846]],[\"comment/1895\",[]],[\"name/1896\",[306,59.846]],[\"comment/1896\",[]],[\"name/1897\",[308,59.846]],[\"comment/1897\",[]],[\"name/1898\",[309,59.846]],[\"comment/1898\",[]],[\"name/1899\",[311,59.846]],[\"comment/1899\",[]],[\"name/1900\",[292,59.846]],[\"comment/1900\",[]],[\"name/1901\",[294,59.846]],[\"comment/1901\",[]],[\"name/1902\",[296,59.846]],[\"comment/1902\",[]],[\"name/1903\",[297,59.846]],[\"comment/1903\",[]],[\"name/1904\",[315,59.846]],[\"comment/1904\",[]],[\"name/1905\",[344,59.846]],[\"comment/1905\",[]],[\"name/1906\",[316,59.846]],[\"comment/1906\",[]],[\"name/1907\",[319,59.846]],[\"comment/1907\",[]],[\"name/1908\",[321,59.846]],[\"comment/1908\",[]],[\"name/1909\",[322,59.846]],[\"comment/1909\",[]],[\"name/1910\",[323,59.846]],[\"comment/1910\",[]],[\"name/1911\",[324,59.846]],[\"comment/1911\",[]],[\"name/1912\",[325,59.846]],[\"comment/1912\",[]],[\"name/1913\",[326,59.846]],[\"comment/1913\",[]],[\"name/1914\",[327,59.846]],[\"comment/1914\",[]],[\"name/1915\",[328,59.846]],[\"comment/1915\",[]],[\"name/1916\",[329,59.846]],[\"comment/1916\",[]],[\"name/1917\",[330,59.846]],[\"comment/1917\",[]],[\"name/1918\",[331,59.846]],[\"comment/1918\",[]],[\"name/1919\",[332,59.846]],[\"comment/1919\",[]],[\"name/1920\",[339,59.846]],[\"comment/1920\",[]],[\"name/1921\",[335,59.846]],[\"comment/1921\",[]],[\"name/1922\",[336,59.846]],[\"comment/1922\",[]],[\"name/1923\",[318,59.846]],[\"comment/1923\",[]],[\"name/1924\",[337,59.846]],[\"comment/1924\",[]],[\"name/1925\",[340,59.846]],[\"comment/1925\",[]],[\"name/1926\",[341,59.846]],[\"comment/1926\",[]],[\"name/1927\",[342,59.846]],[\"comment/1927\",[]],[\"name/1928\",[293,59.846]],[\"comment/1928\",[]],[\"name/1929\",[333,59.846]],[\"comment/1929\",[]],[\"name/1930\",[334,59.846]],[\"comment/1930\",[]],[\"name/1931\",[343,59.846]],[\"comment/1931\",[]],[\"name/1932\",[346,59.846]],[\"comment/1932\",[]],[\"name/1933\",[345,59.846]],[\"comment/1933\",[]],[\"name/1934\",[347,59.846]],[\"comment/1934\",[]],[\"name/1935\",[348,59.846]],[\"comment/1935\",[]],[\"name/1936\",[349,59.846]],[\"comment/1936\",[]],[\"name/1937\",[350,59.846]],[\"comment/1937\",[]],[\"name/1938\",[338,59.846]],[\"comment/1938\",[]],[\"name/1939\",[320,59.846]],[\"comment/1939\",[]],[\"name/1940\",[300,59.846]],[\"comment/1940\",[]],[\"name/1941\",[301,59.846]],[\"comment/1941\",[]],[\"name/1942\",[314,59.846]],[\"comment/1942\",[]],[\"name/1943\",[305,59.846]],[\"comment/1943\",[]],[\"name/1944\",[307,59.846]],[\"comment/1944\",[]],[\"name/1945\",[312,59.846]],[\"comment/1945\",[]],[\"name/1946\",[352,59.846]],[\"comment/1946\",[]],[\"name/1947\",[353,59.846]],[\"comment/1947\",[]],[\"name/1948\",[354,59.846]],[\"comment/1948\",[]],[\"name/1949\",[355,59.846]],[\"comment/1949\",[]],[\"name/1950\",[310,59.846]],[\"comment/1950\",[]],[\"name/1951\",[295,59.846]],[\"comment/1951\",[]],[\"name/1952\",[356,59.846]],[\"comment/1952\",[]],[\"name/1953\",[357,59.846]],[\"comment/1953\",[]],[\"name/1954\",[358,59.846]],[\"comment/1954\",[]],[\"name/1955\",[359,59.846]],[\"comment/1955\",[]],[\"name/1956\",[360,59.846]],[\"comment/1956\",[]],[\"name/1957\",[361,59.846]],[\"comment/1957\",[]],[\"name/1958\",[362,59.846]],[\"comment/1958\",[]],[\"name/1959\",[363,59.846]],[\"comment/1959\",[]],[\"name/1960\",[364,59.846]],[\"comment/1960\",[]],[\"name/1961\",[351,59.846]],[\"comment/1961\",[]],[\"name/1962\",[365,59.846]],[\"comment/1962\",[]],[\"name/1963\",[366,59.846]],[\"comment/1963\",[]],[\"name/1964\",[368,59.846]],[\"comment/1964\",[]],[\"name/1965\",[369,59.846]],[\"comment/1965\",[]],[\"name/1966\",[370,59.846]],[\"comment/1966\",[]],[\"name/1967\",[371,59.846]],[\"comment/1967\",[]],[\"name/1968\",[823,72.839]],[\"comment/1968\",[]],[\"name/1969\",[824,72.839]],[\"comment/1969\",[]],[\"name/1970\",[640,33.136]],[\"comment/1970\",[]],[\"name/1971\",[825,72.839]],[\"comment/1971\",[]],[\"name/1972\",[826,72.839]],[\"comment/1972\",[]],[\"name/1973\",[827,72.839]],[\"comment/1973\",[]],[\"name/1974\",[828,72.839]],[\"comment/1974\",[]],[\"name/1975\",[829,72.839]],[\"comment/1975\",[]],[\"name/1976\",[830,72.839]],[\"comment/1976\",[]],[\"name/1977\",[831,72.839]],[\"comment/1977\",[]],[\"name/1978\",[832,72.839]],[\"comment/1978\",[]],[\"name/1979\",[833,72.839]],[\"comment/1979\",[]],[\"name/1980\",[834,72.839]],[\"comment/1980\",[]],[\"name/1981\",[835,72.839]],[\"comment/1981\",[]],[\"name/1982\",[836,72.839]],[\"comment/1982\",[]],[\"name/1983\",[837,72.839]],[\"comment/1983\",[]],[\"name/1984\",[838,72.839]],[\"comment/1984\",[]],[\"name/1985\",[839,72.839]],[\"comment/1985\",[]],[\"name/1986\",[840,59.846]],[\"comment/1986\",[]],[\"name/1987\",[841,72.839]],[\"comment/1987\",[]],[\"name/1988\",[640,33.136]],[\"comment/1988\",[]],[\"name/1989\",[840,59.846]],[\"comment/1989\",[]],[\"name/1990\",[842,72.839]],[\"comment/1990\",[]],[\"name/1991\",[640,33.136]],[\"comment/1991\",[]],[\"name/1992\",[651,67.731]],[\"comment/1992\",[]],[\"name/1993\",[652,67.731]],[\"comment/1993\",[]],[\"name/1994\",[843,72.839]],[\"comment/1994\",[]],[\"name/1995\",[640,33.136]],[\"comment/1995\",[]],[\"name/1996\",[139,58.176]],[\"comment/1996\",[]],[\"name/1997\",[607,67.731]],[\"comment/1997\",[]],[\"name/1998\",[844,72.839]],[\"comment/1998\",[]],[\"name/1999\",[640,33.136]],[\"comment/1999\",[]],[\"name/2000\",[714,61.853]],[\"comment/2000\",[]],[\"name/2001\",[845,72.839]],[\"comment/2001\",[]],[\"name/2002\",[640,33.136]],[\"comment/2002\",[]],[\"name/2003\",[195,48.86]],[\"comment/2003\",[]],[\"name/2004\",[846,72.839]],[\"comment/2004\",[]],[\"name/2005\",[640,33.136]],[\"comment/2005\",[]],[\"name/2006\",[172,49.485]],[\"comment/2006\",[]],[\"name/2007\",[517,48.86]],[\"comment/2007\",[]],[\"name/2008\",[847,72.839]],[\"comment/2008\",[]],[\"name/2009\",[640,33.136]],[\"comment/2009\",[]],[\"name/2010\",[171,59.846]],[\"comment/2010\",[]],[\"name/2011\",[164,59.846]],[\"comment/2011\",[]],[\"name/2012\",[263,67.731]],[\"comment/2012\",[]],[\"name/2013\",[640,33.136]],[\"comment/2013\",[]],[\"name/2014\",[848,72.839]],[\"comment/2014\",[]],[\"name/2015\",[389,67.731]],[\"comment/2015\",[]],[\"name/2016\",[849,72.839]],[\"comment/2016\",[]],[\"name/2017\",[640,33.136]],[\"comment/2017\",[]],[\"name/2018\",[266,51.636]],[\"comment/2018\",[]],[\"name/2019\",[226,52.47]],[\"comment/2019\",[]],[\"name/2020\",[850,72.839]],[\"comment/2020\",[]],[\"name/2021\",[851,72.839]],[\"comment/2021\",[]],[\"name/2022\",[852,72.839]],[\"comment/2022\",[]],[\"name/2023\",[640,33.136]],[\"comment/2023\",[]],[\"name/2024\",[266,51.636]],[\"comment/2024\",[]],[\"name/2025\",[172,49.485]],[\"comment/2025\",[]],[\"name/2026\",[436,59.846]],[\"comment/2026\",[]],[\"name/2027\",[437,59.846]],[\"comment/2027\",[]],[\"name/2028\",[853,72.839]],[\"comment/2028\",[]],[\"name/2029\",[640,33.136]],[\"comment/2029\",[]],[\"name/2030\",[226,52.47]],[\"comment/2030\",[]],[\"name/2031\",[450,64.366]],[\"comment/2031\",[]],[\"name/2032\",[854,72.839]],[\"comment/2032\",[]],[\"name/2033\",[640,33.136]],[\"comment/2033\",[]],[\"name/2034\",[855,67.731]],[\"comment/2034\",[]],[\"name/2035\",[856,72.839]],[\"comment/2035\",[]],[\"name/2036\",[640,33.136]],[\"comment/2036\",[]],[\"name/2037\",[857,72.839]],[\"comment/2037\",[]],[\"name/2038\",[640,33.136]],[\"comment/2038\",[]],[\"name/2039\",[178,61.853]],[\"comment/2039\",[]],[\"name/2040\",[855,67.731]],[\"comment/2040\",[]],[\"name/2041\",[122,67.731]],[\"comment/2041\",[]],[\"name/2042\",[687,64.366]],[\"comment/2042\",[]],[\"name/2043\",[140,64.366]],[\"comment/2043\",[]],[\"name/2044\",[139,58.176]],[\"comment/2044\",[]],[\"name/2045\",[96,51.636]],[\"comment/2045\",[]],[\"name/2046\",[659,64.366]],[\"comment/2046\",[]],[\"name/2047\",[660,64.366]],[\"comment/2047\",[]],[\"name/2048\",[141,59.846]],[\"comment/2048\",[]],[\"name/2049\",[142,64.366]],[\"comment/2049\",[]],[\"name/2050\",[67,56.745]],[\"comment/2050\",[]],[\"name/2051\",[110,61.853]],[\"comment/2051\",[]],[\"name/2052\",[161,54.381]],[\"comment/2052\",[]],[\"name/2053\",[858,72.839]],[\"comment/2053\",[]],[\"name/2054\",[859,72.839]],[\"comment/2054\",[]],[\"name/2055\",[640,33.136]],[\"comment/2055\",[]],[\"name/2056\",[27,67.731]],[\"comment/2056\",[]],[\"name/2057\",[860,72.839]],[\"comment/2057\",[]],[\"name/2058\",[640,33.136]],[\"comment/2058\",[]],[\"name/2059\",[266,51.636]],[\"comment/2059\",[]],[\"name/2060\",[861,72.839]],[\"comment/2060\",[]],[\"name/2061\",[640,33.136]],[\"comment/2061\",[]],[\"name/2062\",[172,49.485]],[\"comment/2062\",[]],[\"name/2063\",[517,48.86]],[\"comment/2063\",[]],[\"name/2064\",[862,72.839]],[\"comment/2064\",[]],[\"name/2065\",[863,72.839]],[\"comment/2065\",[]],[\"name/2066\",[640,33.136]],[\"comment/2066\",[]],[\"name/2067\",[266,51.636]],[\"comment/2067\",[]],[\"name/2068\",[178,61.853]],[\"comment/2068\",[]],[\"name/2069\",[687,64.366]],[\"comment/2069\",[]],[\"name/2070\",[96,51.636]],[\"comment/2070\",[]],[\"name/2071\",[730,64.366]],[\"comment/2071\",[]],[\"name/2072\",[107,56.745]],[\"comment/2072\",[]],[\"name/2073\",[67,56.745]],[\"comment/2073\",[]],[\"name/2074\",[161,54.381]],[\"comment/2074\",[]],[\"name/2075\",[864,72.839]],[\"comment/2075\",[]],[\"name/2076\",[640,33.136]],[\"comment/2076\",[]],[\"name/2077\",[171,59.846]],[\"comment/2077\",[]],[\"name/2078\",[865,72.839]],[\"comment/2078\",[]],[\"name/2079\",[640,33.136]],[\"comment/2079\",[]],[\"name/2080\",[265,61.853]],[\"comment/2080\",[]],[\"name/2081\",[866,72.839]],[\"comment/2081\",[]],[\"name/2082\",[867,72.839]],[\"comment/2082\",[]],[\"name/2083\",[868,72.839]],[\"comment/2083\",[]],[\"name/2084\",[640,33.136]],[\"comment/2084\",[]],[\"name/2085\",[171,59.846]],[\"comment/2085\",[]],[\"name/2086\",[869,72.839]],[\"comment/2086\",[]],[\"name/2087\",[640,33.136]],[\"comment/2087\",[]],[\"name/2088\",[870,72.839]],[\"comment/2088\",[]],[\"name/2089\",[626,67.731]],[\"comment/2089\",[]],[\"name/2090\",[871,72.839]],[\"comment/2090\",[]],[\"name/2091\",[640,33.136]],[\"comment/2091\",[]],[\"name/2092\",[96,51.636]],[\"comment/2092\",[]],[\"name/2093\",[872,72.839]],[\"comment/2093\",[]],[\"name/2094\",[83,67.731]],[\"comment/2094\",[]],[\"name/2095\",[640,33.136]],[\"comment/2095\",[]],[\"name/2096\",[873,72.839]],[\"comment/2096\",[]],[\"name/2097\",[874,72.839]],[\"comment/2097\",[]],[\"name/2098\",[875,72.839]],[\"comment/2098\",[]],[\"name/2099\",[640,33.136]],[\"comment/2099\",[]],[\"name/2100\",[876,72.839]],[\"comment/2100\",[]],[\"name/2101\",[877,72.839]],[\"comment/2101\",[]],[\"name/2102\",[878,72.839]],[\"comment/2102\",[]],[\"name/2103\",[640,33.136]],[\"comment/2103\",[]],[\"name/2104\",[248,67.731]],[\"comment/2104\",[]],[\"name/2105\",[640,33.136]],[\"comment/2105\",[]],[\"name/2106\",[879,72.839]],[\"comment/2106\",[]],[\"name/2107\",[880,72.839]],[\"comment/2107\",[]],[\"name/2108\",[125,64.366]],[\"comment/2108\",[]],[\"name/2109\",[881,72.839]],[\"comment/2109\",[]],[\"name/2110\",[245,67.731]],[\"comment/2110\",[]],[\"name/2111\",[882,72.839]],[\"comment/2111\",[]],[\"name/2112\",[640,33.136]],[\"comment/2112\",[]],[\"name/2113\",[139,58.176]],[\"comment/2113\",[]],[\"name/2114\",[883,67.731]],[\"comment/2114\",[]],[\"name/2115\",[884,72.839]],[\"comment/2115\",[]],[\"name/2116\",[640,33.136]],[\"comment/2116\",[]],[\"name/2117\",[714,61.853]],[\"comment/2117\",[]],[\"name/2118\",[885,72.839]],[\"comment/2118\",[]],[\"name/2119\",[640,33.136]],[\"comment/2119\",[]],[\"name/2120\",[883,67.731]],[\"comment/2120\",[]],[\"name/2121\",[886,72.839]],[\"comment/2121\",[]],[\"name/2122\",[887,72.839]],[\"comment/2122\",[]],[\"name/2123\",[640,33.136]],[\"comment/2123\",[]],[\"name/2124\",[840,59.846]],[\"comment/2124\",[]],[\"name/2125\",[86,54.381]],[\"comment/2125\",[]],[\"name/2126\",[537,67.731]],[\"comment/2126\",[]],[\"name/2127\",[888,72.839]],[\"comment/2127\",[]],[\"name/2128\",[640,33.136]],[\"comment/2128\",[]],[\"name/2129\",[889,72.839]],[\"comment/2129\",[]],[\"name/2130\",[840,59.846]],[\"comment/2130\",[]],[\"name/2131\",[890,72.839]],[\"comment/2131\",[]],[\"name/2132\",[891,72.839]],[\"comment/2132\",[]],[\"name/2133\",[640,33.136]],[\"comment/2133\",[]],[\"name/2134\",[840,59.846]],[\"comment/2134\",[]],[\"name/2135\",[892,72.839]],[\"comment/2135\",[]],[\"name/2136\",[893,72.839]],[\"comment/2136\",[]],[\"name/2137\",[640,33.136]],[\"comment/2137\",[]],[\"name/2138\",[519,67.731]],[\"comment/2138\",[]],[\"name/2139\",[894,72.839]],[\"comment/2139\",[]],[\"name/2140\",[40,47.716]],[\"comment/2140\",[]],[\"name/2141\",[895,72.839]],[\"comment/2141\",[]],[\"name/2142\",[896,72.839]],[\"comment/2142\",[]],[\"name/2143\",[897,72.839]],[\"comment/2143\",[]],[\"name/2144\",[658,67.731]],[\"comment/2144\",[]],[\"name/2145\",[898,72.839]],[\"comment/2145\",[]],[\"name/2146\",[899,72.839]],[\"comment/2146\",[]],[\"name/2147\",[900,72.839]],[\"comment/2147\",[]],[\"name/2148\",[901,72.839]],[\"comment/2148\",[]],[\"name/2149\",[902,72.839]],[\"comment/2149\",[]],[\"name/2150\",[903,72.839]],[\"comment/2150\",[]],[\"name/2151\",[904,72.839]],[\"comment/2151\",[]],[\"name/2152\",[905,72.839]],[\"comment/2152\",[]],[\"name/2153\",[906,72.839]],[\"comment/2153\",[]],[\"name/2154\",[907,72.839]],[\"comment/2154\",[]],[\"name/2155\",[908,72.839]],[\"comment/2155\",[]],[\"name/2156\",[909,72.839]],[\"comment/2156\",[]],[\"name/2157\",[157,48.272]],[\"comment/2157\",[]],[\"name/2158\",[910,72.839]],[\"comment/2158\",[]],[\"name/2159\",[911,72.839]],[\"comment/2159\",[]],[\"name/2160\",[161,54.381]],[\"comment/2160\",[]],[\"name/2161\",[912,72.839]],[\"comment/2161\",[]],[\"name/2162\",[160,54.381]],[\"comment/2162\",[]],[\"name/2163\",[913,72.839]],[\"comment/2163\",[]],[\"name/2164\",[914,72.839]],[\"comment/2164\",[]],[\"name/2165\",[915,72.839]],[\"comment/2165\",[]],[\"name/2166\",[916,67.731]],[\"comment/2166\",[]],[\"name/2167\",[388,58.176]],[\"comment/2167\",[]],[\"name/2168\",[917,67.731]],[\"comment/2168\",[]],[\"name/2169\",[918,72.839]],[\"comment/2169\",[]],[\"name/2170\",[916,67.731]],[\"comment/2170\",[]],[\"name/2171\",[603,64.366]],[\"comment/2171\",[]],[\"name/2172\",[388,58.176]],[\"comment/2172\",[]],[\"name/2173\",[917,67.731]],[\"comment/2173\",[]],[\"name/2174\",[919,72.839]],[\"comment/2174\",[]],[\"name/2175\",[920,72.839]],[\"comment/2175\",[]],[\"name/2176\",[40,47.716]],[\"comment/2176\",[]],[\"name/2177\",[921,72.839]],[\"comment/2177\",[]],[\"name/2178\",[76,67.731]],[\"comment/2178\",[]],[\"name/2179\",[51,33.521]],[\"comment/2179\",[]],[\"name/2180\",[922,72.839]],[\"comment/2180\",[]],[\"name/2181\",[388,58.176]],[\"comment/2181\",[]],[\"name/2182\",[603,64.366]],[\"comment/2182\",[]],[\"name/2183\",[923,72.839]],[\"comment/2183\",[]]],\"invertedIndex\":[[\"__insert__\",{\"_index\":896,\"name\":{\"2142\":{}},\"comment\":{}}],[\"__nomigrations__\",{\"_index\":611,\"name\":{\"1488\":{}},\"comment\":{}}],[\"__select__\",{\"_index\":895,\"name\":{\"2141\":{}},\"comment\":{}}],[\"__type\",{\"_index\":40,\"name\":{\"41\":{},\"156\":{},\"170\":{},\"374\":{},\"472\":{},\"708\":{},\"710\":{},\"820\":{},\"918\":{},\"1010\":{},\"1018\":{},\"1156\":{},\"1162\":{},\"1164\":{},\"1314\":{},\"1325\":{},\"2140\":{},\"2176\":{}},\"comment\":{}}],[\"__update__\",{\"_index\":897,\"name\":{\"2143\":{}},\"comment\":{}}],[\"acquireconnection\",{\"_index\":478,\"name\":{\"924\":{},\"953\":{},\"1024\":{},\"1178\":{},\"1304\":{}},\"comment\":{}}],[\"acquiremigrationlock\",{\"_index\":503,\"name\":{\"967\":{},\"977\":{},\"1145\":{},\"1299\":{},\"1453\":{}},\"comment\":{}}],[\"adapter\",{\"_index\":273,\"name\":{\"518\":{},\"532\":{},\"546\":{}},\"comment\":{}}],[\"addcheckconstraint\",{\"_index\":409,\"name\":{\"694\":{},\"840\":{}},\"comment\":{}}],[\"addcolumn\",{\"_index\":406,\"name\":{\"691\":{},\"837\":{},\"853\":{},\"860\":{}},\"comment\":{}}],[\"addcolumnnode\",{\"_index\":639,\"name\":{\"1534\":{}},\"comment\":{}}],[\"addconstraint\",{\"_index\":649,\"name\":{\"1562\":{}},\"comment\":{}}],[\"addconstraintnode\",{\"_index\":641,\"name\":{\"1537\":{}},\"comment\":{}}],[\"addforeignkeyconstraint\",{\"_index\":410,\"name\":{\"695\":{},\"841\":{}},\"comment\":{}}],[\"addparameter\",{\"_index\":382,\"name\":{\"660\":{},\"1131\":{},\"1285\":{},\"1439\":{}},\"comment\":{}}],[\"addprimarykeyconstraint\",{\"_index\":407,\"name\":{\"692\":{}},\"comment\":{}}],[\"adduniqueconstraint\",{\"_index\":408,\"name\":{\"693\":{},\"839\":{}},\"comment\":{}}],[\"affectedrows\",{\"_index\":558,\"name\":{\"1172\":{}},\"comment\":{}}],[\"agg\",{\"_index\":210,\"name\":{\"395\":{}},\"comment\":{}}],[\"aggregated\",{\"_index\":880,\"name\":{\"2107\":{}},\"comment\":{}}],[\"aggregatefunctionbuilder\",{\"_index\":236,\"name\":{\"451\":{}},\"comment\":{}}],[\"aggregatefunctionbuilderprops\",{\"_index\":247,\"name\":{\"469\":{}},\"comment\":{}}],[\"aggregatefunctionnode\",{\"_index\":248,\"name\":{\"470\":{},\"2104\":{}},\"comment\":{}}],[\"alias\",{\"_index\":90,\"name\":{\"135\":{},\"1543\":{}},\"comment\":{}}],[\"aliasedaggregatefunctionbuilder\",{\"_index\":246,\"name\":{\"466\":{}},\"comment\":{}}],[\"aliasedexpression\",{\"_index\":89,\"name\":{\"133\":{}},\"comment\":{}}],[\"aliasedexpressionwrapper\",{\"_index\":94,\"name\":{\"142\":{}},\"comment\":{}}],[\"aliasedrawbuilder\",{\"_index\":261,\"name\":{\"499\":{}},\"comment\":{}}],[\"aliasedselectquerybuilder\",{\"_index\":165,\"name\":{\"245\":{}},\"comment\":{}}],[\"aliasnode\",{\"_index\":642,\"name\":{\"1540\":{}},\"comment\":{}}],[\"all\",{\"_index\":537,\"name\":{\"1016\":{},\"2126\":{}},\"comment\":{}}],[\"altercolumn\",{\"_index\":452,\"name\":{\"834\":{},\"850\":{},\"857\":{}},\"comment\":{}}],[\"altercolumnbuilder\",{\"_index\":467,\"name\":{\"898\":{}},\"comment\":{}}],[\"altercolumnbuildercallback\",{\"_index\":475,\"name\":{\"917\":{}},\"comment\":{}}],[\"altercolumnnode\",{\"_index\":468,\"name\":{\"900\":{},\"910\":{},\"1545\":{}},\"comment\":{}}],[\"altercolumnnodeprops\",{\"_index\":643,\"name\":{\"1544\":{}},\"comment\":{}}],[\"alteredcolumnbuilder\",{\"_index\":474,\"name\":{\"907\":{}},\"comment\":{}}],[\"altertable\",{\"_index\":397,\"name\":{\"678\":{}},\"comment\":{}}],[\"altertablebuilder\",{\"_index\":449,\"name\":{\"830\":{}},\"comment\":{}}],[\"altertablebuilderprops\",{\"_index\":457,\"name\":{\"845\":{}},\"comment\":{}}],[\"altertablecolumnalterationnode\",{\"_index\":646,\"name\":{\"1555\":{}},\"comment\":{}}],[\"altertablecolumnalteringbuilder\",{\"_index\":459,\"name\":{\"855\":{}},\"comment\":{}}],[\"altertablecolumnalteringbuilderprops\",{\"_index\":460,\"name\":{\"865\":{}},\"comment\":{}}],[\"altertablenode\",{\"_index\":647,\"name\":{\"1556\":{}},\"comment\":{}}],[\"altertablenodetableprops\",{\"_index\":645,\"name\":{\"1554\":{}},\"comment\":{}}],[\"always\",{\"_index\":710,\"name\":{\"1728\":{}},\"comment\":{}}],[\"and\",{\"_index\":12,\"name\":{\"12\":{}},\"comment\":{}}],[\"andnode\",{\"_index\":650,\"name\":{\"1564\":{}},\"comment\":{}}],[\"anyaliasedcolumn\",{\"_index\":15,\"name\":{\"16\":{}},\"comment\":{}}],[\"anyaliasedcolumnwithtable\",{\"_index\":16,\"name\":{\"17\":{}},\"comment\":{}}],[\"anycolumn\",{\"_index\":17,\"name\":{\"18\":{}},\"comment\":{}}],[\"anycolumnwithtable\",{\"_index\":18,\"name\":{\"19\":{}},\"comment\":{}}],[\"anyselectquerybuilder\",{\"_index\":19,\"name\":{\"20\":{}},\"comment\":{}}],[\"append\",{\"_index\":372,\"name\":{\"650\":{},\"1122\":{},\"1283\":{},\"1435\":{}},\"comment\":{}}],[\"appendimmediatevalue\",{\"_index\":383,\"name\":{\"661\":{},\"1132\":{},\"1286\":{},\"1440\":{}},\"comment\":{}}],[\"appendvalue\",{\"_index\":373,\"name\":{\"651\":{},\"1123\":{},\"1284\":{},\"1436\":{}},\"comment\":{}}],[\"arithmetic_operators\",{\"_index\":830,\"name\":{\"1976\":{}},\"comment\":{}}],[\"arithmeticoperator\",{\"_index\":836,\"name\":{\"1982\":{}},\"comment\":{}}],[\"as\",{\"_index\":92,\"name\":{\"139\":{},\"218\":{},\"453\":{},\"492\":{},\"876\":{},\"1653\":{}},\"comment\":{}}],[\"asenum\",{\"_index\":415,\"name\":{\"714\":{}},\"comment\":{}}],[\"asserttype\",{\"_index\":156,\"name\":{\"231\":{},\"232\":{},\"269\":{},\"270\":{},\"309\":{},\"310\":{},\"354\":{},\"355\":{}},\"comment\":{}}],[\"asynciterator\",{\"_index\":556,\"name\":{\"1170\":{},\"1331\":{}},\"comment\":{}}],[\"autoincrement\",{\"_index\":433,\"name\":{\"801\":{},\"1585\":{}},\"comment\":{}}],[\"avg\",{\"_index\":211,\"name\":{\"396\":{}},\"comment\":{}}],[\"begintransaction\",{\"_index\":479,\"name\":{\"925\":{},\"954\":{},\"1025\":{},\"1179\":{},\"1305\":{}},\"comment\":{}}],[\"binary_operators\",{\"_index\":831,\"name\":{\"1977\":{}},\"comment\":{}}],[\"binaryoperationnode\",{\"_index\":888,\"name\":{\"2127\":{}},\"comment\":{}}],[\"binaryoperator\",{\"_index\":837,\"name\":{\"1983\":{}},\"comment\":{}}],[\"bxp\",{\"_index\":7,\"name\":{\"7\":{}},\"comment\":{}}],[\"bydefault\",{\"_index\":709,\"name\":{\"1727\":{}},\"comment\":{}}],[\"call\",{\"_index\":153,\"name\":{\"224\":{},\"225\":{},\"262\":{},\"263\":{},\"302\":{},\"303\":{},\"347\":{},\"348\":{},\"389\":{},\"430\":{},\"449\":{},\"464\":{},\"698\":{},\"699\":{},\"715\":{},\"726\":{},\"737\":{},\"755\":{},\"768\":{},\"779\":{},\"791\":{},\"817\":{},\"828\":{},\"843\":{},\"844\":{},\"877\":{},\"890\":{},\"906\":{},\"916\":{}},\"comment\":{}}],[\"camelcase\",{\"_index\":636,\"name\":{\"1525\":{}},\"comment\":{}}],[\"camelcaseplugin\",{\"_index\":632,\"name\":{\"1518\":{}},\"comment\":{}}],[\"camelcasepluginoptions\",{\"_index\":627,\"name\":{\"1513\":{}},\"comment\":{}}],[\"cascade\",{\"_index\":419,\"name\":{\"725\":{},\"767\":{},\"790\":{},\"889\":{},\"1688\":{},\"1694\":{},\"1700\":{},\"1712\":{}},\"comment\":{}}],[\"case\",{\"_index\":3,\"name\":{\"3\":{},\"56\":{},\"87\":{}},\"comment\":{}}],[\"casebuilder\",{\"_index\":250,\"name\":{\"473\":{}},\"comment\":{}}],[\"caseendbuilder\",{\"_index\":258,\"name\":{\"485\":{}},\"comment\":{}}],[\"casenode\",{\"_index\":653,\"name\":{\"1568\":{}},\"comment\":{}}],[\"casethenbuilder\",{\"_index\":252,\"name\":{\"476\":{}},\"comment\":{}}],[\"casewhenbuilder\",{\"_index\":254,\"name\":{\"479\":{}},\"comment\":{}}],[\"castto\",{\"_index\":93,\"name\":{\"140\":{},\"228\":{},\"229\":{},\"266\":{},\"267\":{},\"306\":{},\"307\":{},\"351\":{},\"352\":{},\"493\":{},\"494\":{}},\"comment\":{}}],[\"changes\",{\"_index\":539,\"name\":{\"1019\":{}},\"comment\":{}}],[\"check\",{\"_index\":441,\"name\":{\"810\":{},\"1589\":{}},\"comment\":{}}],[\"checkconstraintnode\",{\"_index\":655,\"name\":{\"1574\":{}},\"comment\":{}}],[\"clearlimit\",{\"_index\":150,\"name\":{\"221\":{}},\"comment\":{}}],[\"clearoffset\",{\"_index\":151,\"name\":{\"222\":{}},\"comment\":{}}],[\"clearorderby\",{\"_index\":152,\"name\":{\"223\":{}},\"comment\":{}}],[\"clearselect\",{\"_index\":149,\"name\":{\"219\":{}},\"comment\":{}}],[\"clearwhere\",{\"_index\":104,\"name\":{\"154\":{},\"220\":{},\"293\":{},\"337\":{},\"427\":{},\"448\":{}},\"comment\":{}}],[\"close\",{\"_index\":533,\"name\":{\"1012\":{},\"1323\":{}},\"comment\":{}}],[\"cmpr\",{\"_index\":6,\"name\":{\"6\":{}},\"comment\":{}}],[\"coalesce\",{\"_index\":212,\"name\":{\"397\":{}},\"comment\":{}}],[\"column\",{\"_index\":226,\"name\":{\"415\":{},\"750\":{},\"1536\":{},\"1547\":{},\"1581\":{},\"1596\":{},\"1599\":{},\"1675\":{},\"1771\":{},\"2019\":{},\"2030\":{}},\"comment\":{}}],[\"columnalterations\",{\"_index\":648,\"name\":{\"1561\":{}},\"comment\":{}}],[\"columnalteringinterface\",{\"_index\":458,\"name\":{\"849\":{}},\"comment\":{}}],[\"columnbuildercallback\",{\"_index\":412,\"name\":{\"707\":{}},\"comment\":{}}],[\"columndatatype\",{\"_index\":681,\"name\":{\"1654\":{}},\"comment\":{}}],[\"columndefinitionbuilder\",{\"_index\":432,\"name\":{\"799\":{}},\"comment\":{}}],[\"columndefinitionbuildercallback\",{\"_index\":446,\"name\":{\"819\":{}},\"comment\":{}}],[\"columndefinitionnode\",{\"_index\":657,\"name\":{\"1579\":{}},\"comment\":{}}],[\"columndefinitionnodeprops\",{\"_index\":656,\"name\":{\"1578\":{}},\"comment\":{}}],[\"columnmetadata\",{\"_index\":522,\"name\":{\"994\":{}},\"comment\":{}}],[\"columnnode\",{\"_index\":661,\"name\":{\"1594\":{}},\"comment\":{}}],[\"columns\",{\"_index\":172,\"name\":{\"255\":{},\"416\":{},\"751\":{},\"875\":{},\"992\":{},\"1608\":{},\"1616\":{},\"1632\":{},\"1652\":{},\"1716\":{},\"1748\":{},\"1778\":{},\"2006\":{},\"2025\":{},\"2062\":{}},\"comment\":{}}],[\"columntype\",{\"_index\":894,\"name\":{\"2139\":{}},\"comment\":{}}],[\"columnupdatenode\",{\"_index\":662,\"name\":{\"1597\":{}},\"comment\":{}}],[\"command\",{\"_index\":574,\"name\":{\"1327\":{}},\"comment\":{}}],[\"committransaction\",{\"_index\":480,\"name\":{\"926\":{},\"955\":{},\"1026\":{},\"1180\":{},\"1306\":{}},\"comment\":{}}],[\"commontableexpressionnamenode\",{\"_index\":664,\"name\":{\"1605\":{}},\"comment\":{}}],[\"commontableexpressionnode\",{\"_index\":663,\"name\":{\"1601\":{}},\"comment\":{}}],[\"comparison_operators\",{\"_index\":829,\"name\":{\"1975\":{}},\"comment\":{}}],[\"comparisonoperator\",{\"_index\":835,\"name\":{\"1981\":{}},\"comment\":{}}],[\"comparisonoperatorexpression\",{\"_index\":45,\"name\":{\"46\":{}},\"comment\":{}}],[\"compilable\",{\"_index\":909,\"name\":{\"2156\":{}},\"comment\":{}}],[\"compile\",{\"_index\":157,\"name\":{\"235\":{},\"273\":{},\"313\":{},\"358\":{},\"497\":{},\"701\":{},\"716\":{},\"728\":{},\"739\":{},\"757\":{},\"770\":{},\"781\":{},\"793\":{},\"863\":{},\"879\":{},\"892\":{},\"2157\":{}},\"comment\":{}}],[\"compiledistincton\",{\"_index\":290,\"name\":{\"568\":{},\"1040\":{},\"1201\":{},\"1355\":{}},\"comment\":{}}],[\"compiledquery\",{\"_index\":387,\"name\":{\"665\":{},\"666\":{}},\"comment\":{}}],[\"compilelist\",{\"_index\":291,\"name\":{\"569\":{},\"1041\":{},\"1202\":{},\"1356\":{}},\"comment\":{}}],[\"compilequery\",{\"_index\":275,\"name\":{\"521\":{},\"533\":{},\"547\":{},\"562\":{},\"1034\":{},\"1195\":{},\"1349\":{},\"1457\":{}},\"comment\":{}}],[\"compileunwrappedidentifier\",{\"_index\":302,\"name\":{\"580\":{},\"1052\":{},\"1213\":{},\"1367\":{}},\"comment\":{}}],[\"condition\",{\"_index\":870,\"name\":{\"2088\":{}},\"comment\":{}}],[\"config\",{\"_index\":70,\"name\":{\"98\":{}},\"comment\":{}}],[\"connect\",{\"_index\":568,\"name\":{\"1316\":{}},\"comment\":{}}],[\"connection\",{\"_index\":56,\"name\":{\"59\":{},\"78\":{}},\"comment\":{}}],[\"connectionbuilder\",{\"_index\":77,\"name\":{\"106\":{}},\"comment\":{}}],[\"connectionprovider\",{\"_index\":492,\"name\":{\"942\":{}},\"comment\":{}}],[\"constraint\",{\"_index\":227,\"name\":{\"417\":{},\"1539\":{},\"1779\":{}},\"comment\":{}}],[\"constraintname\",{\"_index\":691,\"name\":{\"1679\":{}},\"comment\":{}}],[\"constraintnode\",{\"_index\":665,\"name\":{\"1609\":{}},\"comment\":{}}],[\"constraints\",{\"_index\":675,\"name\":{\"1633\":{}},\"comment\":{}}],[\"constructor\",{\"_index\":51,\"name\":{\"52\":{},\"75\":{},\"107\":{},\"110\":{},\"114\":{},\"138\":{},\"143\":{},\"172\":{},\"246\":{},\"253\":{},\"284\":{},\"328\":{},\"376\":{},\"379\":{},\"404\":{},\"408\":{},\"411\":{},\"414\":{},\"436\":{},\"439\":{},\"452\":{},\"467\":{},\"474\":{},\"477\":{},\"480\":{},\"486\":{},\"491\":{},\"500\":{},\"531\":{},\"545\":{},\"560\":{},\"671\":{},\"687\":{},\"712\":{},\"723\":{},\"735\":{},\"746\":{},\"764\":{},\"777\":{},\"788\":{},\"800\":{},\"825\":{},\"831\":{},\"856\":{},\"870\":{},\"886\":{},\"899\":{},\"908\":{},\"920\":{},\"945\":{},\"948\":{},\"951\":{},\"974\":{},\"1002\":{},\"1022\":{},\"1031\":{},\"1137\":{},\"1142\":{},\"1148\":{},\"1176\":{},\"1185\":{},\"1291\":{},\"1296\":{},\"1302\":{},\"1333\":{},\"1339\":{},\"1445\":{},\"1450\":{},\"1466\":{},\"1494\":{},\"1519\":{},\"1527\":{},\"1531\":{},\"1796\":{},\"1883\":{},\"2179\":{}},\"comment\":{}}],[\"count\",{\"_index\":213,\"name\":{\"398\":{}},\"comment\":{}}],[\"countall\",{\"_index\":214,\"name\":{\"399\":{}},\"comment\":{}}],[\"createadapter\",{\"_index\":498,\"name\":{\"962\":{},\"1005\":{},\"1151\":{},\"1336\":{}},\"comment\":{}}],[\"createdriver\",{\"_index\":496,\"name\":{\"960\":{},\"1003\":{},\"1149\":{},\"1334\":{}},\"comment\":{}}],[\"createfunctionmodule\",{\"_index\":208,\"name\":{\"393\":{}},\"comment\":{}}],[\"createindex\",{\"_index\":393,\"name\":{\"674\":{}},\"comment\":{}}],[\"createindexbuilder\",{\"_index\":423,\"name\":{\"745\":{}},\"comment\":{}}],[\"createindexbuilderprops\",{\"_index\":425,\"name\":{\"759\":{}},\"comment\":{}}],[\"createindexnode\",{\"_index\":668,\"name\":{\"1612\":{}},\"comment\":{}}],[\"createindexnodeprops\",{\"_index\":666,\"name\":{\"1610\":{}},\"comment\":{}}],[\"createintrospector\",{\"_index\":499,\"name\":{\"963\":{},\"1006\":{},\"1152\":{},\"1337\":{}},\"comment\":{}}],[\"createquerycompiler\",{\"_index\":497,\"name\":{\"961\":{},\"1004\":{},\"1150\":{},\"1335\":{}},\"comment\":{}}],[\"createschema\",{\"_index\":395,\"name\":{\"676\":{}},\"comment\":{}}],[\"createschemabuilder\",{\"_index\":428,\"name\":{\"776\":{}},\"comment\":{}}],[\"createschemabuilderprops\",{\"_index\":429,\"name\":{\"783\":{}},\"comment\":{}}],[\"createschemanode\",{\"_index\":670,\"name\":{\"1622\":{}},\"comment\":{}}],[\"createschemanodeparams\",{\"_index\":669,\"name\":{\"1621\":{}},\"comment\":{}}],[\"createtable\",{\"_index\":391,\"name\":{\"672\":{}},\"comment\":{}}],[\"createtablebuilder\",{\"_index\":402,\"name\":{\"686\":{}},\"comment\":{}}],[\"createtablebuilderprops\",{\"_index\":411,\"name\":{\"703\":{}},\"comment\":{}}],[\"createtablenode\",{\"_index\":674,\"name\":{\"1629\":{}},\"comment\":{}}],[\"createtablenodeparams\",{\"_index\":673,\"name\":{\"1628\":{}},\"comment\":{}}],[\"createtype\",{\"_index\":400,\"name\":{\"681\":{}},\"comment\":{}}],[\"createtypebuilder\",{\"_index\":414,\"name\":{\"711\":{}},\"comment\":{}}],[\"createtypebuilderprops\",{\"_index\":416,\"name\":{\"718\":{}},\"comment\":{}}],[\"createtypenode\",{\"_index\":677,\"name\":{\"1640\":{}},\"comment\":{}}],[\"createtypenodeparams\",{\"_index\":676,\"name\":{\"1639\":{}},\"comment\":{}}],[\"createview\",{\"_index\":398,\"name\":{\"679\":{}},\"comment\":{}}],[\"createviewbuilder\",{\"_index\":461,\"name\":{\"869\":{}},\"comment\":{}}],[\"createviewbuilderprops\",{\"_index\":464,\"name\":{\"881\":{}},\"comment\":{}}],[\"createviewnode\",{\"_index\":680,\"name\":{\"1645\":{}},\"comment\":{}}],[\"createviewnodeparams\",{\"_index\":679,\"name\":{\"1644\":{}},\"comment\":{}}],[\"cursor\",{\"_index\":566,\"name\":{\"1312\":{}},\"comment\":{}}],[\"database\",{\"_index\":530,\"name\":{\"1008\":{}},\"comment\":{}}],[\"databaseconnection\",{\"_index\":486,\"name\":{\"934\":{}},\"comment\":{}}],[\"databaseintrospector\",{\"_index\":510,\"name\":{\"979\":{}},\"comment\":{}}],[\"databasemetadata\",{\"_index\":518,\"name\":{\"987\":{}},\"comment\":{}}],[\"databasemetadataoptions\",{\"_index\":514,\"name\":{\"983\":{}},\"comment\":{}}],[\"datatype\",{\"_index\":523,\"name\":{\"996\":{},\"1548\":{},\"1582\":{},\"1658\":{}},\"comment\":{}}],[\"datatypeexpression\",{\"_index\":644,\"name\":{\"1549\":{}},\"comment\":{}}],[\"datatypenode\",{\"_index\":683,\"name\":{\"1656\":{}},\"comment\":{}}],[\"datatypeparams\",{\"_index\":682,\"name\":{\"1655\":{}},\"comment\":{}}],[\"datatypeschema\",{\"_index\":524,\"name\":{\"997\":{}},\"comment\":{}}],[\"db\",{\"_index\":597,\"name\":{\"1473\":{}},\"comment\":{}}],[\"deduplicatejoinsplugin\",{\"_index\":637,\"name\":{\"1526\":{}},\"comment\":{}}],[\"default_migration_lock_table\",{\"_index\":584,\"name\":{\"1459\":{}},\"comment\":{}}],[\"default_migration_table\",{\"_index\":583,\"name\":{\"1458\":{}},\"comment\":{}}],[\"defaultconnectionprovider\",{\"_index\":493,\"name\":{\"944\":{}},\"comment\":{}}],[\"defaultinsertvaluenode\",{\"_index\":878,\"name\":{\"2102\":{}},\"comment\":{}}],[\"defaultquerycompiler\",{\"_index\":283,\"name\":{\"559\":{}},\"comment\":{}}],[\"defaultqueryexecutor\",{\"_index\":280,\"name\":{\"530\":{}},\"comment\":{}}],[\"defaultto\",{\"_index\":440,\"name\":{\"809\":{},\"1588\":{}},\"comment\":{}}],[\"defaultvalue\",{\"_index\":685,\"name\":{\"1661\":{}},\"comment\":{}}],[\"defaultvaluenode\",{\"_index\":684,\"name\":{\"1659\":{}},\"comment\":{}}],[\"deletefrom\",{\"_index\":65,\"name\":{\"70\":{},\"93\":{},\"118\":{}},\"comment\":{}}],[\"deletequerybuilder\",{\"_index\":185,\"name\":{\"327\":{}},\"comment\":{}}],[\"deletequerybuilderprops\",{\"_index\":187,\"name\":{\"364\":{}},\"comment\":{}}],[\"deletequerybuilderwithfulljoin\",{\"_index\":191,\"name\":{\"371\":{}},\"comment\":{}}],[\"deletequerybuilderwithinnerjoin\",{\"_index\":188,\"name\":{\"368\":{}},\"comment\":{}}],[\"deletequerybuilderwithleftjoin\",{\"_index\":189,\"name\":{\"369\":{}},\"comment\":{}}],[\"deletequerybuilderwithrightjoin\",{\"_index\":190,\"name\":{\"370\":{}},\"comment\":{}}],[\"deletequerynode\",{\"_index\":686,\"name\":{\"1662\":{}},\"comment\":{}}],[\"deleteresult\",{\"_index\":221,\"name\":{\"407\":{}},\"comment\":{}}],[\"destroy\",{\"_index\":60,\"name\":{\"64\":{},\"79\":{},\"929\":{},\"958\":{},\"1029\":{},\"1183\":{},\"1309\":{}},\"comment\":{}}],[\"dialect\",{\"_index\":73,\"name\":{\"101\":{},\"103\":{},\"959\":{}},\"comment\":{}}],[\"dialectadapter\",{\"_index\":500,\"name\":{\"964\":{}},\"comment\":{}}],[\"dialectadapterbase\",{\"_index\":509,\"name\":{\"973\":{}},\"comment\":{}}],[\"direction\",{\"_index\":607,\"name\":{\"1483\":{},\"1997\":{}},\"comment\":{}}],[\"distinct\",{\"_index\":125,\"name\":{\"194\":{},\"454\":{},\"2108\":{}},\"comment\":{}}],[\"distincton\",{\"_index\":122,\"name\":{\"191\":{},\"2041\":{}},\"comment\":{}}],[\"donothing\",{\"_index\":228,\"name\":{\"428\":{},\"1784\":{}},\"comment\":{}}],[\"doupdateset\",{\"_index\":229,\"name\":{\"429\":{}},\"comment\":{}}],[\"down\",{\"_index\":589,\"name\":{\"1464\":{}},\"comment\":{}}],[\"driver\",{\"_index\":71,\"name\":{\"99\":{},\"922\":{}},\"comment\":{}}],[\"dropcolumn\",{\"_index\":453,\"name\":{\"835\":{},\"851\":{},\"858\":{}},\"comment\":{}}],[\"dropcolumnnode\",{\"_index\":688,\"name\":{\"1673\":{}},\"comment\":{}}],[\"dropconstraint\",{\"_index\":456,\"name\":{\"842\":{},\"1563\":{}},\"comment\":{}}],[\"dropconstraintnode\",{\"_index\":690,\"name\":{\"1677\":{}},\"comment\":{}}],[\"dropconstraintnodeprops\",{\"_index\":689,\"name\":{\"1676\":{}},\"comment\":{}}],[\"dropdefault\",{\"_index\":471,\"name\":{\"903\":{},\"913\":{},\"1551\":{}},\"comment\":{}}],[\"dropindex\",{\"_index\":394,\"name\":{\"675\":{}},\"comment\":{}}],[\"dropindexbuilder\",{\"_index\":426,\"name\":{\"763\":{}},\"comment\":{}}],[\"dropindexbuilderprops\",{\"_index\":427,\"name\":{\"772\":{}},\"comment\":{}}],[\"dropindexnode\",{\"_index\":694,\"name\":{\"1683\":{}},\"comment\":{}}],[\"dropindexnodeprops\",{\"_index\":693,\"name\":{\"1682\":{}},\"comment\":{}}],[\"dropnotnull\",{\"_index\":473,\"name\":{\"905\":{},\"915\":{},\"1553\":{}},\"comment\":{}}],[\"dropschema\",{\"_index\":396,\"name\":{\"677\":{}},\"comment\":{}}],[\"dropschemabuilder\",{\"_index\":430,\"name\":{\"787\":{}},\"comment\":{}}],[\"dropschemabuilderprops\",{\"_index\":431,\"name\":{\"795\":{}},\"comment\":{}}],[\"dropschemanode\",{\"_index\":696,\"name\":{\"1690\":{}},\"comment\":{}}],[\"dropschemanodeparams\",{\"_index\":695,\"name\":{\"1689\":{}},\"comment\":{}}],[\"droptable\",{\"_index\":392,\"name\":{\"673\":{}},\"comment\":{}}],[\"droptablebuilder\",{\"_index\":417,\"name\":{\"722\":{}},\"comment\":{}}],[\"droptablebuilderprops\",{\"_index\":420,\"name\":{\"730\":{}},\"comment\":{}}],[\"droptablenode\",{\"_index\":698,\"name\":{\"1696\":{}},\"comment\":{}}],[\"droptablexnodeparams\",{\"_index\":697,\"name\":{\"1695\":{}},\"comment\":{}}],[\"droptype\",{\"_index\":401,\"name\":{\"682\":{}},\"comment\":{}}],[\"droptypebuilder\",{\"_index\":421,\"name\":{\"734\":{}},\"comment\":{}}],[\"droptypebuilderprops\",{\"_index\":422,\"name\":{\"741\":{}},\"comment\":{}}],[\"droptypenode\",{\"_index\":700,\"name\":{\"1702\":{}},\"comment\":{}}],[\"droptypenodeparams\",{\"_index\":699,\"name\":{\"1701\":{}},\"comment\":{}}],[\"dropview\",{\"_index\":399,\"name\":{\"680\":{}},\"comment\":{}}],[\"dropviewbuilder\",{\"_index\":465,\"name\":{\"885\":{}},\"comment\":{}}],[\"dropviewbuilderprops\",{\"_index\":466,\"name\":{\"894\":{}},\"comment\":{}}],[\"dropviewnode\",{\"_index\":702,\"name\":{\"1707\":{}},\"comment\":{}}],[\"dropviewnodeparams\",{\"_index\":701,\"name\":{\"1706\":{}},\"comment\":{}}],[\"dummydriver\",{\"_index\":495,\"name\":{\"950\":{}},\"comment\":{}}],[\"dynamic\",{\"_index\":53,\"name\":{\"54\":{},\"85\":{}},\"comment\":{}}],[\"dynamicmodule\",{\"_index\":476,\"name\":{\"919\":{}},\"comment\":{}}],[\"else\",{\"_index\":255,\"name\":{\"482\":{},\"1572\":{}},\"comment\":{}}],[\"end\",{\"_index\":256,\"name\":{\"483\":{},\"487\":{},\"1159\":{},\"1317\":{}},\"comment\":{}}],[\"endcase\",{\"_index\":257,\"name\":{\"484\":{},\"488\":{}},\"comment\":{}}],[\"endmodifiers\",{\"_index\":660,\"name\":{\"1593\":{},\"1638\":{},\"2047\":{}},\"comment\":{}}],[\"enum\",{\"_index\":678,\"name\":{\"1643\":{}},\"comment\":{}}],[\"equals\",{\"_index\":20,\"name\":{\"21\":{}},\"comment\":{}}],[\"error\",{\"_index\":603,\"name\":{\"1479\":{},\"2171\":{},\"2182\":{}},\"comment\":{}}],[\"errorlogevent\",{\"_index\":918,\"name\":{\"2169\":{}},\"comment\":{}}],[\"except\",{\"_index\":147,\"name\":{\"216\":{}},\"comment\":{}}],[\"exceptall\",{\"_index\":148,\"name\":{\"217\":{}},\"comment\":{}}],[\"execute\",{\"_index\":78,\"name\":{\"108\":{},\"112\":{},\"236\":{},\"274\":{},\"314\":{},\"359\":{},\"498\":{},\"702\":{},\"717\":{},\"729\":{},\"740\":{},\"758\":{},\"771\":{},\"782\":{},\"794\":{},\"864\":{},\"880\":{},\"893\":{}},\"comment\":{}}],[\"executedat\",{\"_index\":613,\"name\":{\"1492\":{}},\"comment\":{}}],[\"executequery\",{\"_index\":62,\"name\":{\"66\":{},\"89\":{},\"522\":{},\"542\":{},\"556\":{},\"935\":{}},\"comment\":{}}],[\"executetakefirst\",{\"_index\":158,\"name\":{\"237\":{},\"275\":{},\"315\":{},\"360\":{}},\"comment\":{}}],[\"executetakefirstorthrow\",{\"_index\":159,\"name\":{\"238\":{},\"276\":{},\"316\":{},\"361\":{}},\"comment\":{}}],[\"executor\",{\"_index\":72,\"name\":{\"100\":{},\"126\":{},\"244\":{},\"282\":{},\"322\":{},\"367\":{},\"705\":{},\"720\":{},\"732\":{},\"743\":{},\"761\":{},\"774\":{},\"785\":{},\"797\":{},\"847\":{},\"867\":{},\"883\":{},\"896\":{}},\"comment\":{}}],[\"exists\",{\"_index\":10,\"name\":{\"10\":{}},\"comment\":{}}],[\"existsexpression\",{\"_index\":48,\"name\":{\"49\":{}},\"comment\":{}}],[\"explain\",{\"_index\":161,\"name\":{\"240\":{},\"278\":{},\"318\":{},\"363\":{},\"1672\":{},\"1756\":{},\"2052\":{},\"2074\":{},\"2160\":{}},\"comment\":{}}],[\"explainable\",{\"_index\":911,\"name\":{\"2159\":{}},\"comment\":{}}],[\"explainformat\",{\"_index\":910,\"name\":{\"2158\":{}},\"comment\":{}}],[\"explainnode\",{\"_index\":875,\"name\":{\"2098\":{}},\"comment\":{}}],[\"expression\",{\"_index\":86,\"name\":{\"130\":{},\"134\":{},\"256\":{},\"418\":{},\"752\":{},\"1576\":{},\"1604\":{},\"1731\":{},\"2125\":{}},\"comment\":{}}],[\"expressionbuilder\",{\"_index\":0,\"name\":{\"0\":{},\"15\":{}},\"comment\":{}}],[\"expressions\",{\"_index\":873,\"name\":{\"2096\":{}},\"comment\":{}}],[\"expressiontype\",{\"_index\":87,\"name\":{\"131\":{}},\"comment\":{}}],[\"expressionwrapper\",{\"_index\":91,\"name\":{\"137\":{}},\"comment\":{}}],[\"extracttypefromreferenceexpression\",{\"_index\":33,\"name\":{\"34\":{}},\"comment\":{}}],[\"extracttypefromstringreference\",{\"_index\":32,\"name\":{\"33\":{}},\"comment\":{}}],[\"filemigrationprovider\",{\"_index\":614,\"name\":{\"1493\":{}},\"comment\":{}}],[\"filemigrationproviderfs\",{\"_index\":615,\"name\":{\"1496\":{}},\"comment\":{}}],[\"filemigrationproviderpath\",{\"_index\":617,\"name\":{\"1498\":{}},\"comment\":{}}],[\"filemigrationproviderprops\",{\"_index\":618,\"name\":{\"1500\":{}},\"comment\":{}}],[\"filter\",{\"_index\":881,\"name\":{\"2109\":{}},\"comment\":{}}],[\"filterwhere\",{\"_index\":237,\"name\":{\"455\":{}},\"comment\":{}}],[\"filterwhereexists\",{\"_index\":238,\"name\":{\"456\":{}},\"comment\":{}}],[\"filterwherenotexists\",{\"_index\":239,\"name\":{\"457\":{}},\"comment\":{}}],[\"filterwhereref\",{\"_index\":240,\"name\":{\"458\":{}},\"comment\":{}}],[\"fn\",{\"_index\":1,\"name\":{\"1\":{},\"57\":{},\"88\":{}},\"comment\":{}}],[\"foreignkeyconstraintbuilder\",{\"_index\":448,\"name\":{\"824\":{}},\"comment\":{}}],[\"foreignkeyconstraintbuildercallback\",{\"_index\":413,\"name\":{\"709\":{}},\"comment\":{}}],[\"foreignkeyconstraintbuilderinterface\",{\"_index\":447,\"name\":{\"821\":{}},\"comment\":{}}],[\"foreignkeyconstraintnode\",{\"_index\":704,\"name\":{\"1714\":{}},\"comment\":{}}],[\"foreignkeyconstraintnodeprops\",{\"_index\":703,\"name\":{\"1713\":{}},\"comment\":{}}],[\"forkeyshare\",{\"_index\":128,\"name\":{\"197\":{}},\"comment\":{}}],[\"format\",{\"_index\":876,\"name\":{\"2100\":{}},\"comment\":{}}],[\"fornokeyupdate\",{\"_index\":129,\"name\":{\"198\":{}},\"comment\":{}}],[\"forshare\",{\"_index\":127,\"name\":{\"196\":{}},\"comment\":{}}],[\"forupdate\",{\"_index\":126,\"name\":{\"195\":{}},\"comment\":{}}],[\"from\",{\"_index\":178,\"name\":{\"294\":{},\"1664\":{},\"2039\":{},\"2068\":{}},\"comment\":{}}],[\"fromnode\",{\"_index\":705,\"name\":{\"1721\":{}},\"comment\":{}}],[\"froms\",{\"_index\":706,\"name\":{\"1723\":{}},\"comment\":{}}],[\"frontmodifiers\",{\"_index\":659,\"name\":{\"1592\":{},\"1637\":{},\"2046\":{}},\"comment\":{}}],[\"fs\",{\"_index\":619,\"name\":{\"1501\":{}},\"comment\":{}}],[\"fulljoin\",{\"_index\":136,\"name\":{\"205\":{},\"298\":{},\"342\":{}},\"comment\":{}}],[\"func\",{\"_index\":879,\"name\":{\"2106\":{}},\"comment\":{}}],[\"functionmodule\",{\"_index\":209,\"name\":{\"394\":{}},\"comment\":{}}],[\"generated\",{\"_index\":658,\"name\":{\"1590\":{},\"2144\":{}},\"comment\":{}}],[\"generatedalways\",{\"_index\":898,\"name\":{\"2145\":{}},\"comment\":{}}],[\"generatedalwaysas\",{\"_index\":442,\"name\":{\"811\":{}},\"comment\":{}}],[\"generatedalwaysasidentity\",{\"_index\":443,\"name\":{\"812\":{}},\"comment\":{}}],[\"generatedbydefaultasidentity\",{\"_index\":444,\"name\":{\"813\":{}},\"comment\":{}}],[\"generatednode\",{\"_index\":708,\"name\":{\"1725\":{}},\"comment\":{}}],[\"generatednodeparams\",{\"_index\":707,\"name\":{\"1724\":{}},\"comment\":{}}],[\"getautoincrement\",{\"_index\":317,\"name\":{\"595\":{},\"1067\":{},\"1228\":{},\"1345\":{}},\"comment\":{}}],[\"getconnection\",{\"_index\":549,\"name\":{\"1158\":{}},\"comment\":{}}],[\"getcurrentparameterplaceholder\",{\"_index\":376,\"name\":{\"654\":{},\"1126\":{},\"1186\":{},\"1340\":{}},\"comment\":{}}],[\"getexplainoptionassignment\",{\"_index\":378,\"name\":{\"656\":{},\"1128\":{},\"1188\":{},\"1437\":{}},\"comment\":{}}],[\"getexplainoptionsdelimiter\",{\"_index\":379,\"name\":{\"657\":{},\"1129\":{},\"1189\":{},\"1438\":{}},\"comment\":{}}],[\"getleftexplainoptionswrapper\",{\"_index\":377,\"name\":{\"655\":{},\"1127\":{},\"1187\":{},\"1341\":{}},\"comment\":{}}],[\"getleftidentifierwrapper\",{\"_index\":374,\"name\":{\"652\":{},\"1124\":{},\"1191\":{},\"1343\":{}},\"comment\":{}}],[\"getmetadata\",{\"_index\":513,\"name\":{\"982\":{},\"1140\":{},\"1294\":{},\"1448\":{}},\"comment\":{}}],[\"getmigrations\",{\"_index\":591,\"name\":{\"1467\":{},\"1486\":{},\"1495\":{}},\"comment\":{}}],[\"getrightexplainoptionswrapper\",{\"_index\":380,\"name\":{\"658\":{},\"1130\":{},\"1190\":{},\"1342\":{}},\"comment\":{}}],[\"getrightidentifierwrapper\",{\"_index\":375,\"name\":{\"653\":{},\"1125\":{},\"1192\":{},\"1344\":{}},\"comment\":{}}],[\"getschemas\",{\"_index\":511,\"name\":{\"980\":{},\"1138\":{},\"1292\":{},\"1446\":{}},\"comment\":{}}],[\"getsql\",{\"_index\":285,\"name\":{\"563\":{},\"1035\":{},\"1196\":{},\"1350\":{}},\"comment\":{}}],[\"gettables\",{\"_index\":512,\"name\":{\"981\":{},\"1139\":{},\"1293\":{},\"1447\":{}},\"comment\":{}}],[\"groupby\",{\"_index\":140,\"name\":{\"209\":{},\"1734\":{},\"2043\":{}},\"comment\":{}}],[\"groupbyitemnode\",{\"_index\":712,\"name\":{\"1732\":{}},\"comment\":{}}],[\"groupbynode\",{\"_index\":713,\"name\":{\"1735\":{}},\"comment\":{}}],[\"hasdefaultvalue\",{\"_index\":527,\"name\":{\"1000\":{}},\"comment\":{}}],[\"having\",{\"_index\":110,\"name\":{\"161\":{},\"181\":{},\"1740\":{},\"2051\":{}},\"comment\":{}}],[\"havingexists\",{\"_index\":114,\"name\":{\"165\":{},\"185\":{}},\"comment\":{}}],[\"havingexpressionfactory\",{\"_index\":118,\"name\":{\"169\":{}},\"comment\":{}}],[\"havinginterface\",{\"_index\":109,\"name\":{\"160\":{}},\"comment\":{}}],[\"havingnode\",{\"_index\":715,\"name\":{\"1738\":{}},\"comment\":{}}],[\"havingnotexist\",{\"_index\":120,\"name\":{\"186\":{}},\"comment\":{}}],[\"havingnotexists\",{\"_index\":115,\"name\":{\"166\":{},\"187\":{}},\"comment\":{}}],[\"havingref\",{\"_index\":111,\"name\":{\"162\":{},\"182\":{}},\"comment\":{}}],[\"highwatermark\",{\"_index\":553,\"name\":{\"1167\":{}},\"comment\":{}}],[\"id\",{\"_index\":267,\"name\":{\"511\":{}},\"comment\":{}}],[\"identifiernode\",{\"_index\":716,\"name\":{\"1741\":{}},\"comment\":{}}],[\"identity\",{\"_index\":711,\"name\":{\"1729\":{}},\"comment\":{}}],[\"if\",{\"_index\":154,\"name\":{\"226\":{},\"227\":{},\"264\":{},\"265\":{},\"304\":{},\"305\":{},\"349\":{},\"350\":{}},\"comment\":{}}],[\"ifexists\",{\"_index\":418,\"name\":{\"724\":{},\"736\":{},\"766\":{},\"789\":{},\"888\":{},\"1680\":{},\"1687\":{},\"1693\":{},\"1699\":{},\"1705\":{},\"1710\":{}},\"comment\":{}}],[\"ifnotexists\",{\"_index\":405,\"name\":{\"690\":{},\"747\":{},\"778\":{},\"873\":{},\"1619\":{},\"1625\":{},\"1635\":{},\"1651\":{}},\"comment\":{}}],[\"ignore\",{\"_index\":173,\"name\":{\"257\":{},\"1754\":{}},\"comment\":{}}],[\"immediate\",{\"_index\":866,\"name\":{\"2081\":{}},\"comment\":{}}],[\"indexexpression\",{\"_index\":728,\"name\":{\"1780\":{}},\"comment\":{}}],[\"indextype\",{\"_index\":667,\"name\":{\"1611\":{}},\"comment\":{}}],[\"indexwhere\",{\"_index\":729,\"name\":{\"1781\":{}},\"comment\":{}}],[\"inferresult\",{\"_index\":923,\"name\":{\"2183\":{}},\"comment\":{}}],[\"init\",{\"_index\":477,\"name\":{\"923\":{},\"952\":{},\"1023\":{},\"1177\":{},\"1303\":{}},\"comment\":{}}],[\"innerjoin\",{\"_index\":133,\"name\":{\"202\":{},\"295\":{},\"339\":{}},\"comment\":{}}],[\"innerjoinlateral\",{\"_index\":137,\"name\":{\"206\":{}},\"comment\":{}}],[\"insertable\",{\"_index\":906,\"name\":{\"2153\":{}},\"comment\":{}}],[\"insertid\",{\"_index\":219,\"name\":{\"405\":{},\"940\":{},\"1173\":{}},\"comment\":{}}],[\"insertinto\",{\"_index\":63,\"name\":{\"68\":{},\"91\":{},\"116\":{}},\"comment\":{}}],[\"insertobject\",{\"_index\":41,\"name\":{\"42\":{}},\"comment\":{}}],[\"insertquerybuilder\",{\"_index\":170,\"name\":{\"252\":{}},\"comment\":{}}],[\"insertquerybuilderprops\",{\"_index\":176,\"name\":{\"279\":{}},\"comment\":{}}],[\"insertquerynode\",{\"_index\":718,\"name\":{\"1745\":{}},\"comment\":{}}],[\"insertquerynodeprops\",{\"_index\":717,\"name\":{\"1744\":{}},\"comment\":{}}],[\"insertresult\",{\"_index\":218,\"name\":{\"403\":{}},\"comment\":{}}],[\"inserttype\",{\"_index\":900,\"name\":{\"2147\":{}},\"comment\":{}}],[\"intersect\",{\"_index\":145,\"name\":{\"214\":{}},\"comment\":{}}],[\"intersectall\",{\"_index\":146,\"name\":{\"215\":{}},\"comment\":{}}],[\"into\",{\"_index\":719,\"name\":{\"1747\":{}},\"comment\":{}}],[\"introspection\",{\"_index\":54,\"name\":{\"55\":{},\"86\":{}},\"comment\":{}}],[\"isaliasedexpression\",{\"_index\":85,\"name\":{\"129\":{}},\"comment\":{}}],[\"isarithmeticoperator\",{\"_index\":828,\"name\":{\"1974\":{}},\"comment\":{}}],[\"isautoincrementing\",{\"_index\":525,\"name\":{\"998\":{}},\"comment\":{}}],[\"isbinaryoperator\",{\"_index\":826,\"name\":{\"1972\":{}},\"comment\":{}}],[\"iscomparisonoperator\",{\"_index\":827,\"name\":{\"1973\":{}},\"comment\":{}}],[\"iscompilable\",{\"_index\":908,\"name\":{\"2155\":{}},\"comment\":{}}],[\"isexpression\",{\"_index\":84,\"name\":{\"128\":{}},\"comment\":{}}],[\"iskyselyprops\",{\"_index\":49,\"name\":{\"50\":{}},\"comment\":{}}],[\"islevelenabled\",{\"_index\":922,\"name\":{\"2180\":{}},\"comment\":{}}],[\"isminusoperator\",{\"_index\":367,\"name\":{\"645\":{},\"1117\":{},\"1278\":{},\"1430\":{}},\"comment\":{}}],[\"isnoresulterrorconstructor\",{\"_index\":192,\"name\":{\"372\":{}},\"comment\":{}}],[\"isnullable\",{\"_index\":526,\"name\":{\"999\":{}},\"comment\":{}}],[\"isolationlevel\",{\"_index\":484,\"name\":{\"931\":{},\"933\":{}},\"comment\":{}}],[\"isoperationnodesource\",{\"_index\":735,\"name\":{\"1792\":{}},\"comment\":{}}],[\"isoperator\",{\"_index\":825,\"name\":{\"1971\":{}},\"comment\":{}}],[\"israwbuilder\",{\"_index\":259,\"name\":{\"489\":{}},\"comment\":{}}],[\"isstatement\",{\"_index\":654,\"name\":{\"1573\":{}},\"comment\":{}}],[\"istransaction\",{\"_index\":61,\"name\":{\"65\":{},\"76\":{}},\"comment\":{}}],[\"isview\",{\"_index\":521,\"name\":{\"991\":{}},\"comment\":{}}],[\"items\",{\"_index\":714,\"name\":{\"1737\":{},\"1768\":{},\"2000\":{},\"2117\":{}},\"comment\":{}}],[\"join\",{\"_index\":271,\"name\":{\"515\":{},\"1499\":{}},\"comment\":{}}],[\"joinbuilder\",{\"_index\":196,\"name\":{\"378\":{}},\"comment\":{}}],[\"joinbuilderprops\",{\"_index\":206,\"name\":{\"391\":{}},\"comment\":{}}],[\"joincallbackexpression\",{\"_index\":39,\"name\":{\"40\":{}},\"comment\":{}}],[\"joinnode\",{\"_index\":207,\"name\":{\"392\":{},\"1758\":{}},\"comment\":{}}],[\"joinreferenceexpression\",{\"_index\":38,\"name\":{\"39\":{}},\"comment\":{}}],[\"joins\",{\"_index\":687,\"name\":{\"1666\":{},\"2042\":{},\"2069\":{}},\"comment\":{}}],[\"jointype\",{\"_index\":722,\"name\":{\"1757\":{},\"1760\":{}},\"comment\":{}}],[\"kind\",{\"_index\":640,\"name\":{\"1535\":{},\"1538\":{},\"1541\":{},\"1546\":{},\"1557\":{},\"1565\":{},\"1569\":{},\"1575\":{},\"1580\":{},\"1595\":{},\"1598\":{},\"1602\":{},\"1606\":{},\"1613\":{},\"1623\":{},\"1630\":{},\"1641\":{},\"1646\":{},\"1657\":{},\"1660\":{},\"1663\":{},\"1674\":{},\"1678\":{},\"1684\":{},\"1691\":{},\"1697\":{},\"1703\":{},\"1708\":{},\"1715\":{},\"1722\":{},\"1726\":{},\"1733\":{},\"1736\":{},\"1739\":{},\"1742\":{},\"1746\":{},\"1759\":{},\"1764\":{},\"1767\":{},\"1770\":{},\"1773\":{},\"1777\":{},\"1787\":{},\"1790\":{},\"1970\":{},\"1988\":{},\"1991\":{},\"1995\":{},\"1999\":{},\"2002\":{},\"2005\":{},\"2009\":{},\"2013\":{},\"2017\":{},\"2023\":{},\"2029\":{},\"2033\":{},\"2036\":{},\"2038\":{},\"2055\":{},\"2058\":{},\"2061\":{},\"2066\":{},\"2076\":{},\"2079\":{},\"2084\":{},\"2087\":{},\"2091\":{},\"2095\":{},\"2099\":{},\"2103\":{},\"2105\":{},\"2112\":{},\"2116\":{},\"2119\":{},\"2123\":{},\"2128\":{},\"2133\":{},\"2137\":{}},\"comment\":{}}],[\"kysely\",{\"_index\":50,\"name\":{\"51\":{}},\"comment\":{}}],[\"kyselyconfig\",{\"_index\":74,\"name\":{\"102\":{}},\"comment\":{}}],[\"kyselyplugin\",{\"_index\":622,\"name\":{\"1504\":{}},\"comment\":{}}],[\"kyselyprops\",{\"_index\":69,\"name\":{\"97\":{}},\"comment\":{}}],[\"lastinsertrowid\",{\"_index\":540,\"name\":{\"1020\":{}},\"comment\":{}}],[\"left\",{\"_index\":651,\"name\":{\"1566\":{},\"1992\":{}},\"comment\":{}}],[\"leftjoin\",{\"_index\":134,\"name\":{\"203\":{},\"296\":{},\"340\":{}},\"comment\":{}}],[\"leftjoinlateral\",{\"_index\":138,\"name\":{\"207\":{}},\"comment\":{}}],[\"leftoperand\",{\"_index\":889,\"name\":{\"2129\":{}},\"comment\":{}}],[\"level\",{\"_index\":916,\"name\":{\"2166\":{},\"2170\":{}},\"comment\":{}}],[\"limit\",{\"_index\":141,\"name\":{\"210\":{},\"346\":{},\"1671\":{},\"1765\":{},\"2048\":{}},\"comment\":{}}],[\"limitnode\",{\"_index\":723,\"name\":{\"1763\":{}},\"comment\":{}}],[\"listnode\",{\"_index\":724,\"name\":{\"1766\":{}},\"comment\":{}}],[\"lit\",{\"_index\":268,\"name\":{\"512\":{}},\"comment\":{}}],[\"literal\",{\"_index\":269,\"name\":{\"513\":{}},\"comment\":{}}],[\"lockrowid\",{\"_index\":507,\"name\":{\"971\":{}},\"comment\":{}}],[\"locktable\",{\"_index\":506,\"name\":{\"970\":{}},\"comment\":{}}],[\"locktableschema\",{\"_index\":508,\"name\":{\"972\":{}},\"comment\":{}}],[\"log\",{\"_index\":76,\"name\":{\"105\":{},\"2178\":{}},\"comment\":{}}],[\"log_levels\",{\"_index\":913,\"name\":{\"2163\":{}},\"comment\":{}}],[\"logconfig\",{\"_index\":921,\"name\":{\"2177\":{}},\"comment\":{}}],[\"logevent\",{\"_index\":919,\"name\":{\"2174\":{}},\"comment\":{}}],[\"logger\",{\"_index\":920,\"name\":{\"2175\":{}},\"comment\":{}}],[\"loglevel\",{\"_index\":914,\"name\":{\"2164\":{}},\"comment\":{}}],[\"logonce\",{\"_index\":24,\"name\":{\"25\":{}},\"comment\":{}}],[\"maintainnestedobjectkeys\",{\"_index\":631,\"name\":{\"1517\":{}},\"comment\":{}}],[\"maprow\",{\"_index\":634,\"name\":{\"1523\":{}},\"comment\":{}}],[\"materialized\",{\"_index\":462,\"name\":{\"872\":{},\"887\":{},\"1649\":{},\"1711\":{}},\"comment\":{}}],[\"max\",{\"_index\":215,\"name\":{\"400\":{}},\"comment\":{}}],[\"migratedown\",{\"_index\":595,\"name\":{\"1471\":{}},\"comment\":{}}],[\"migrateto\",{\"_index\":593,\"name\":{\"1469\":{}},\"comment\":{}}],[\"migratetolatest\",{\"_index\":592,\"name\":{\"1468\":{}},\"comment\":{}}],[\"migrateup\",{\"_index\":594,\"name\":{\"1470\":{}},\"comment\":{}}],[\"migration\",{\"_index\":587,\"name\":{\"1462\":{},\"1491\":{}},\"comment\":{}}],[\"migration_lock_id\",{\"_index\":585,\"name\":{\"1460\":{}},\"comment\":{}}],[\"migrationfolder\",{\"_index\":621,\"name\":{\"1503\":{}},\"comment\":{}}],[\"migrationinfo\",{\"_index\":612,\"name\":{\"1489\":{}},\"comment\":{}}],[\"migrationlockoptions\",{\"_index\":505,\"name\":{\"969\":{}},\"comment\":{}}],[\"migrationlocktablename\",{\"_index\":600,\"name\":{\"1476\":{}},\"comment\":{}}],[\"migrationname\",{\"_index\":606,\"name\":{\"1482\":{}},\"comment\":{}}],[\"migrationprovider\",{\"_index\":609,\"name\":{\"1485\":{}},\"comment\":{}}],[\"migrationresult\",{\"_index\":605,\"name\":{\"1481\":{}},\"comment\":{}}],[\"migrationresultset\",{\"_index\":602,\"name\":{\"1478\":{}},\"comment\":{}}],[\"migrationtablename\",{\"_index\":599,\"name\":{\"1475\":{}},\"comment\":{}}],[\"migrationtableschema\",{\"_index\":601,\"name\":{\"1477\":{}},\"comment\":{}}],[\"migrator\",{\"_index\":590,\"name\":{\"1465\":{}},\"comment\":{}}],[\"migratorprops\",{\"_index\":596,\"name\":{\"1472\":{}},\"comment\":{}}],[\"min\",{\"_index\":216,\"name\":{\"401\":{}},\"comment\":{}}],[\"modifier\",{\"_index\":692,\"name\":{\"1681\":{}},\"comment\":{}}],[\"modifycolumn\",{\"_index\":455,\"name\":{\"838\":{},\"854\":{},\"861\":{}},\"comment\":{}}],[\"modifycolumnnode\",{\"_index\":725,\"name\":{\"1769\":{}},\"comment\":{}}],[\"modifyend\",{\"_index\":124,\"name\":{\"193\":{},\"697\":{},\"816\":{}},\"comment\":{}}],[\"modifyfront\",{\"_index\":123,\"name\":{\"192\":{},\"696\":{},\"815\":{}},\"comment\":{}}],[\"mysqladapter\",{\"_index\":563,\"name\":{\"1295\":{}},\"comment\":{}}],[\"mysqldialect\",{\"_index\":545,\"name\":{\"1147\":{}},\"comment\":{}}],[\"mysqldialectconfig\",{\"_index\":546,\"name\":{\"1153\":{}},\"comment\":{}}],[\"mysqldriver\",{\"_index\":560,\"name\":{\"1175\":{}},\"comment\":{}}],[\"mysqlintrospector\",{\"_index\":562,\"name\":{\"1290\":{}},\"comment\":{}}],[\"mysqlokpacket\",{\"_index\":557,\"name\":{\"1171\":{}},\"comment\":{}}],[\"mysqlpool\",{\"_index\":548,\"name\":{\"1157\":{}},\"comment\":{}}],[\"mysqlpoolconnection\",{\"_index\":550,\"name\":{\"1160\":{}},\"comment\":{}}],[\"mysqlquerycompiler\",{\"_index\":561,\"name\":{\"1184\":{}},\"comment\":{}}],[\"mysqlqueryresult\",{\"_index\":559,\"name\":{\"1174\":{}},\"comment\":{}}],[\"mysqlstream\",{\"_index\":555,\"name\":{\"1169\":{}},\"comment\":{}}],[\"mysqlstreamoptions\",{\"_index\":552,\"name\":{\"1166\":{}},\"comment\":{}}],[\"name\",{\"_index\":517,\"name\":{\"986\":{},\"990\":{},\"995\":{},\"1490\":{},\"1577\":{},\"1603\":{},\"1614\":{},\"1642\":{},\"1647\":{},\"1685\":{},\"1704\":{},\"1709\":{},\"1720\":{},\"1743\":{},\"2007\":{},\"2063\":{}},\"comment\":{}}],[\"narrowtype\",{\"_index\":155,\"name\":{\"230\":{},\"268\":{},\"308\":{},\"353\":{}},\"comment\":{}}],[\"neg\",{\"_index\":11,\"name\":{\"11\":{}},\"comment\":{}}],[\"no_migrations\",{\"_index\":586,\"name\":{\"1461\":{}},\"comment\":{}}],[\"node\",{\"_index\":195,\"name\":{\"377\":{},\"706\":{},\"721\":{},\"733\":{},\"744\":{},\"762\":{},\"775\":{},\"786\":{},\"798\":{},\"848\":{},\"868\":{},\"884\":{},\"897\":{},\"1509\":{},\"1542\":{},\"2003\":{}},\"comment\":{}}],[\"nodestack\",{\"_index\":384,\"name\":{\"662\":{},\"1133\":{},\"1287\":{},\"1441\":{},\"1797\":{},\"1884\":{}},\"comment\":{}}],[\"nomigrations\",{\"_index\":610,\"name\":{\"1487\":{}},\"comment\":{}}],[\"nonnullableinsertkeys\",{\"_index\":903,\"name\":{\"2150\":{}},\"comment\":{}}],[\"noop_query_executor\",{\"_index\":282,\"name\":{\"558\":{}},\"comment\":{}}],[\"noopqueryexecutor\",{\"_index\":281,\"name\":{\"544\":{}},\"comment\":{}}],[\"noresulterror\",{\"_index\":194,\"name\":{\"375\":{}},\"comment\":{}}],[\"noresulterrorconstructor\",{\"_index\":193,\"name\":{\"373\":{}},\"comment\":{}}],[\"not\",{\"_index\":9,\"name\":{\"9\":{}},\"comment\":{}}],[\"notnull\",{\"_index\":438,\"name\":{\"807\":{},\"1587\":{}},\"comment\":{}}],[\"nowait\",{\"_index\":131,\"name\":{\"200\":{}},\"comment\":{}}],[\"nullableinsertkeys\",{\"_index\":902,\"name\":{\"2149\":{}},\"comment\":{}}],[\"numaffectedrows\",{\"_index\":490,\"name\":{\"939\":{}},\"comment\":{}}],[\"numdeletedrows\",{\"_index\":222,\"name\":{\"409\":{}},\"comment\":{}}],[\"numinsertedorupdatedrows\",{\"_index\":220,\"name\":{\"406\":{}},\"comment\":{}}],[\"numparameters\",{\"_index\":284,\"name\":{\"561\":{},\"1033\":{},\"1194\":{},\"1348\":{}},\"comment\":{}}],[\"numupdatedordeletedrows\",{\"_index\":489,\"name\":{\"938\":{}},\"comment\":{}}],[\"numupdatedrows\",{\"_index\":224,\"name\":{\"412\":{}},\"comment\":{}}],[\"objectmode\",{\"_index\":554,\"name\":{\"1168\":{}},\"comment\":{}}],[\"offset\",{\"_index\":142,\"name\":{\"211\":{},\"1774\":{},\"2049\":{}},\"comment\":{}}],[\"offsetnode\",{\"_index\":726,\"name\":{\"1772\":{}},\"comment\":{}}],[\"on\",{\"_index\":197,\"name\":{\"380\":{},\"749\":{},\"765\":{},\"1762\":{},\"1791\":{}},\"comment\":{}}],[\"on_commit_actions\",{\"_index\":671,\"name\":{\"1626\":{}},\"comment\":{}}],[\"on_modify_foreign_actions\",{\"_index\":850,\"name\":{\"2020\":{}},\"comment\":{}}],[\"oncommit\",{\"_index\":404,\"name\":{\"689\":{},\"1636\":{}},\"comment\":{}}],[\"oncommitaction\",{\"_index\":672,\"name\":{\"1627\":{}},\"comment\":{}}],[\"onconflict\",{\"_index\":174,\"name\":{\"258\":{},\"1751\":{}},\"comment\":{}}],[\"onconflictbuilder\",{\"_index\":225,\"name\":{\"413\":{}},\"comment\":{}}],[\"onconflictbuilderprops\",{\"_index\":230,\"name\":{\"431\":{}},\"comment\":{}}],[\"onconflictdatabase\",{\"_index\":232,\"name\":{\"433\":{}},\"comment\":{}}],[\"onconflictdonothingbuilder\",{\"_index\":234,\"name\":{\"435\":{}},\"comment\":{}}],[\"onconflictnode\",{\"_index\":231,\"name\":{\"432\":{},\"1776\":{}},\"comment\":{}}],[\"onconflictnodeprops\",{\"_index\":727,\"name\":{\"1775\":{}},\"comment\":{}}],[\"onconflicttables\",{\"_index\":233,\"name\":{\"434\":{}},\"comment\":{}}],[\"onconflictupdatebuilder\",{\"_index\":235,\"name\":{\"438\":{}},\"comment\":{}}],[\"oncreateconnection\",{\"_index\":531,\"name\":{\"1009\":{},\"1155\":{},\"1313\":{}},\"comment\":{}}],[\"ondelete\",{\"_index\":436,\"name\":{\"804\":{},\"822\":{},\"826\":{},\"1718\":{},\"2026\":{}},\"comment\":{}}],[\"onduplicatekey\",{\"_index\":720,\"name\":{\"1752\":{}},\"comment\":{}}],[\"onduplicatekeynode\",{\"_index\":733,\"name\":{\"1786\":{}},\"comment\":{}}],[\"onduplicatekeynodeprops\",{\"_index\":732,\"name\":{\"1785\":{}},\"comment\":{}}],[\"onduplicatekeyupdate\",{\"_index\":175,\"name\":{\"259\":{}},\"comment\":{}}],[\"onexists\",{\"_index\":201,\"name\":{\"384\":{}},\"comment\":{}}],[\"onmodifyforeignaction\",{\"_index\":851,\"name\":{\"2021\":{}},\"comment\":{}}],[\"onnode\",{\"_index\":734,\"name\":{\"1789\":{}},\"comment\":{}}],[\"onnotexists\",{\"_index\":202,\"name\":{\"385\":{}},\"comment\":{}}],[\"onref\",{\"_index\":199,\"name\":{\"382\":{}},\"comment\":{}}],[\"ontrue\",{\"_index\":205,\"name\":{\"388\":{}},\"comment\":{}}],[\"onupdate\",{\"_index\":437,\"name\":{\"805\":{},\"823\":{},\"827\":{},\"1719\":{},\"2027\":{}},\"comment\":{}}],[\"operand\",{\"_index\":892,\"name\":{\"2135\":{}},\"comment\":{}}],[\"operandvalueexpression\",{\"_index\":46,\"name\":{\"47\":{}},\"comment\":{}}],[\"operandvalueexpressionorlist\",{\"_index\":47,\"name\":{\"48\":{}},\"comment\":{}}],[\"operationnode\",{\"_index\":824,\"name\":{\"1969\":{}},\"comment\":{}}],[\"operationnodekind\",{\"_index\":823,\"name\":{\"1968\":{}},\"comment\":{}}],[\"operationnodesource\",{\"_index\":736,\"name\":{\"1793\":{}},\"comment\":{}}],[\"operationnodetransformer\",{\"_index\":737,\"name\":{\"1795\":{}},\"comment\":{}}],[\"operationnodevisitor\",{\"_index\":822,\"name\":{\"1882\":{}},\"comment\":{}}],[\"operator\",{\"_index\":840,\"name\":{\"1986\":{},\"1989\":{},\"2124\":{},\"2130\":{},\"2134\":{}},\"comment\":{}}],[\"operatornode\",{\"_index\":841,\"name\":{\"1987\":{}},\"comment\":{}}],[\"operators\",{\"_index\":834,\"name\":{\"1980\":{}},\"comment\":{}}],[\"opt\",{\"_index\":633,\"name\":{\"1520\":{}},\"comment\":{}}],[\"options\",{\"_index\":877,\"name\":{\"2101\":{}},\"comment\":{}}],[\"or\",{\"_index\":13,\"name\":{\"13\":{}},\"comment\":{}}],[\"orderby\",{\"_index\":139,\"name\":{\"208\":{},\"345\":{},\"1670\":{},\"1996\":{},\"2044\":{},\"2113\":{}},\"comment\":{}}],[\"orderbydirectionexpression\",{\"_index\":44,\"name\":{\"45\":{}},\"comment\":{}}],[\"orderbyexpression\",{\"_index\":43,\"name\":{\"44\":{}},\"comment\":{}}],[\"orderbyitemnode\",{\"_index\":843,\"name\":{\"1994\":{}},\"comment\":{}}],[\"orderbynode\",{\"_index\":844,\"name\":{\"1998\":{}},\"comment\":{}}],[\"orfilterwhere\",{\"_index\":241,\"name\":{\"459\":{}},\"comment\":{}}],[\"orfilterwhereexists\",{\"_index\":242,\"name\":{\"460\":{}},\"comment\":{}}],[\"orfilterwherenotexists\",{\"_index\":243,\"name\":{\"461\":{}},\"comment\":{}}],[\"orfilterwhereref\",{\"_index\":244,\"name\":{\"462\":{}},\"comment\":{}}],[\"orhaving\",{\"_index\":112,\"name\":{\"163\":{},\"183\":{}},\"comment\":{}}],[\"orhavingexists\",{\"_index\":116,\"name\":{\"167\":{},\"188\":{}},\"comment\":{}}],[\"orhavingnotexists\",{\"_index\":117,\"name\":{\"168\":{},\"189\":{}},\"comment\":{}}],[\"orhavingref\",{\"_index\":113,\"name\":{\"164\":{},\"184\":{}},\"comment\":{}}],[\"ornode\",{\"_index\":842,\"name\":{\"1990\":{}},\"comment\":{}}],[\"oron\",{\"_index\":198,\"name\":{\"381\":{}},\"comment\":{}}],[\"oronexists\",{\"_index\":203,\"name\":{\"386\":{}},\"comment\":{}}],[\"oronnotexists\",{\"_index\":204,\"name\":{\"387\":{}},\"comment\":{}}],[\"oronref\",{\"_index\":200,\"name\":{\"383\":{}},\"comment\":{}}],[\"orreplace\",{\"_index\":463,\"name\":{\"874\":{},\"1650\":{}},\"comment\":{}}],[\"orwhere\",{\"_index\":98,\"name\":{\"148\":{},\"175\":{},\"287\":{},\"331\":{},\"421\":{},\"442\":{}},\"comment\":{}}],[\"orwhereexists\",{\"_index\":102,\"name\":{\"152\":{},\"179\":{},\"291\":{},\"335\":{},\"425\":{},\"446\":{}},\"comment\":{}}],[\"orwherenotexists\",{\"_index\":103,\"name\":{\"153\":{},\"180\":{},\"292\":{},\"336\":{},\"426\":{},\"447\":{}},\"comment\":{}}],[\"orwhereref\",{\"_index\":99,\"name\":{\"149\":{},\"176\":{},\"288\":{},\"332\":{},\"422\":{},\"443\":{}},\"comment\":{}}],[\"over\",{\"_index\":245,\"name\":{\"463\":{},\"2110\":{}},\"comment\":{}}],[\"overbuildercallback\",{\"_index\":249,\"name\":{\"471\":{}},\"comment\":{}}],[\"overnode\",{\"_index\":882,\"name\":{\"2111\":{}},\"comment\":{}}],[\"parameters\",{\"_index\":389,\"name\":{\"669\":{},\"2015\":{}},\"comment\":{}}],[\"parensnode\",{\"_index\":845,\"name\":{\"2001\":{}},\"comment\":{}}],[\"parentnode\",{\"_index\":385,\"name\":{\"663\":{},\"1134\":{},\"1288\":{},\"1442\":{},\"1885\":{}},\"comment\":{}}],[\"partitionby\",{\"_index\":883,\"name\":{\"2114\":{},\"2120\":{}},\"comment\":{}}],[\"partitionbyitemnode\",{\"_index\":885,\"name\":{\"2118\":{}},\"comment\":{}}],[\"partitionbynode\",{\"_index\":884,\"name\":{\"2115\":{}},\"comment\":{}}],[\"path\",{\"_index\":620,\"name\":{\"1502\":{}},\"comment\":{}}],[\"plugins\",{\"_index\":75,\"name\":{\"104\":{},\"505\":{},\"519\":{},\"540\":{},\"554\":{}},\"comment\":{}}],[\"plugintransformqueryargs\",{\"_index\":624,\"name\":{\"1507\":{}},\"comment\":{}}],[\"plugintransformresultargs\",{\"_index\":625,\"name\":{\"1510\":{}},\"comment\":{}}],[\"pool\",{\"_index\":547,\"name\":{\"1154\":{},\"1311\":{}},\"comment\":{}}],[\"postgresadapter\",{\"_index\":544,\"name\":{\"1141\":{}},\"comment\":{}}],[\"postgrescursor\",{\"_index\":570,\"name\":{\"1321\":{}},\"comment\":{}}],[\"postgrescursorconstructor\",{\"_index\":572,\"name\":{\"1324\":{}},\"comment\":{}}],[\"postgresdialect\",{\"_index\":577,\"name\":{\"1332\":{}},\"comment\":{}}],[\"postgresdialectconfig\",{\"_index\":565,\"name\":{\"1310\":{}},\"comment\":{}}],[\"postgresdriver\",{\"_index\":564,\"name\":{\"1301\":{}},\"comment\":{}}],[\"postgresintrospector\",{\"_index\":543,\"name\":{\"1136\":{}},\"comment\":{}}],[\"postgrespool\",{\"_index\":567,\"name\":{\"1315\":{}},\"comment\":{}}],[\"postgrespoolclient\",{\"_index\":569,\"name\":{\"1318\":{}},\"comment\":{}}],[\"postgresquerycompiler\",{\"_index\":542,\"name\":{\"1030\":{}},\"comment\":{}}],[\"postgresqueryresult\",{\"_index\":573,\"name\":{\"1326\":{}},\"comment\":{}}],[\"postgresstream\",{\"_index\":576,\"name\":{\"1330\":{}},\"comment\":{}}],[\"prepare\",{\"_index\":534,\"name\":{\"1013\":{}},\"comment\":{}}],[\"primarykey\",{\"_index\":434,\"name\":{\"802\":{},\"1584\":{}},\"comment\":{}}],[\"primarykeyconstraintnode\",{\"_index\":846,\"name\":{\"2004\":{}},\"comment\":{}}],[\"primitivevaluelistnode\",{\"_index\":847,\"name\":{\"2008\":{}},\"comment\":{}}],[\"provideconnection\",{\"_index\":279,\"name\":{\"529\":{},\"534\":{},\"548\":{},\"943\":{},\"946\":{},\"949\":{}},\"comment\":{}}],[\"provider\",{\"_index\":598,\"name\":{\"1474\":{}},\"comment\":{}}],[\"query\",{\"_index\":388,\"name\":{\"667\":{},\"1161\":{},\"1319\":{},\"2167\":{},\"2172\":{},\"2181\":{}},\"comment\":{}}],[\"querycompiler\",{\"_index\":582,\"name\":{\"1456\":{}},\"comment\":{}}],[\"querycreator\",{\"_index\":81,\"name\":{\"113\":{}},\"comment\":{}}],[\"querycreatorprops\",{\"_index\":82,\"name\":{\"125\":{}},\"comment\":{}}],[\"querydurationmillis\",{\"_index\":917,\"name\":{\"2168\":{},\"2173\":{}},\"comment\":{}}],[\"queryexecutor\",{\"_index\":272,\"name\":{\"517\":{}},\"comment\":{}}],[\"queryid\",{\"_index\":163,\"name\":{\"242\":{},\"280\":{},\"320\":{},\"365\":{},\"503\":{},\"704\":{},\"719\":{},\"731\":{},\"742\":{},\"760\":{},\"773\":{},\"784\":{},\"796\":{},\"846\":{},\"866\":{},\"882\":{},\"895\":{},\"1508\":{},\"1511\":{}},\"comment\":{}}],[\"querylogevent\",{\"_index\":915,\"name\":{\"2165\":{}},\"comment\":{}}],[\"querynode\",{\"_index\":164,\"name\":{\"243\":{},\"281\":{},\"321\":{},\"366\":{},\"2011\":{}},\"comment\":{}}],[\"queryresult\",{\"_index\":488,\"name\":{\"937\":{}},\"comment\":{}}],[\"raw\",{\"_index\":270,\"name\":{\"514\":{}},\"comment\":{}}],[\"rawbuilder\",{\"_index\":260,\"name\":{\"490\":{}},\"comment\":{}}],[\"rawbuilderprops\",{\"_index\":262,\"name\":{\"502\":{}},\"comment\":{}}],[\"rawnode\",{\"_index\":263,\"name\":{\"504\":{},\"2012\":{}},\"comment\":{}}],[\"read\",{\"_index\":571,\"name\":{\"1322\":{}},\"comment\":{}}],[\"readdir\",{\"_index\":616,\"name\":{\"1497\":{}},\"comment\":{}}],[\"reader\",{\"_index\":536,\"name\":{\"1015\":{}},\"comment\":{}}],[\"recursive\",{\"_index\":874,\"name\":{\"2097\":{}},\"comment\":{}}],[\"ref\",{\"_index\":4,\"name\":{\"4\":{},\"509\":{},\"921\":{}},\"comment\":{}}],[\"referenceexpression\",{\"_index\":28,\"name\":{\"29\":{}},\"comment\":{}}],[\"referenceexpressionorlist\",{\"_index\":29,\"name\":{\"30\":{}},\"comment\":{}}],[\"referencenode\",{\"_index\":849,\"name\":{\"2016\":{}},\"comment\":{}}],[\"references\",{\"_index\":435,\"name\":{\"803\":{},\"1583\":{},\"1717\":{}},\"comment\":{}}],[\"referencesnode\",{\"_index\":852,\"name\":{\"2022\":{}},\"comment\":{}}],[\"release\",{\"_index\":551,\"name\":{\"1165\":{},\"1320\":{}},\"comment\":{}}],[\"releaseconnection\",{\"_index\":482,\"name\":{\"928\":{},\"957\":{},\"1028\":{},\"1182\":{},\"1308\":{}},\"comment\":{}}],[\"releasemigrationlock\",{\"_index\":504,\"name\":{\"968\":{},\"978\":{},\"1146\":{},\"1300\":{},\"1454\":{}},\"comment\":{}}],[\"renamecolumn\",{\"_index\":454,\"name\":{\"836\":{},\"852\":{},\"859\":{}},\"comment\":{}}],[\"renamecolumnnode\",{\"_index\":853,\"name\":{\"2028\":{}},\"comment\":{}}],[\"renameto\",{\"_index\":450,\"name\":{\"832\":{},\"1559\":{},\"2031\":{}},\"comment\":{}}],[\"replace\",{\"_index\":721,\"name\":{\"1755\":{}},\"comment\":{}}],[\"replaceinto\",{\"_index\":64,\"name\":{\"69\":{},\"92\":{},\"117\":{}},\"comment\":{}}],[\"result\",{\"_index\":626,\"name\":{\"1512\":{},\"2089\":{}},\"comment\":{}}],[\"results\",{\"_index\":604,\"name\":{\"1480\":{}},\"comment\":{}}],[\"returning\",{\"_index\":107,\"name\":{\"158\":{},\"260\":{},\"300\":{},\"343\":{},\"1668\":{},\"1750\":{},\"2072\":{}},\"comment\":{}}],[\"returningall\",{\"_index\":108,\"name\":{\"159\":{},\"261\":{},\"301\":{},\"344\":{}},\"comment\":{}}],[\"returninginterface\",{\"_index\":106,\"name\":{\"157\":{}},\"comment\":{}}],[\"returningnode\",{\"_index\":854,\"name\":{\"2032\":{}},\"comment\":{}}],[\"right\",{\"_index\":652,\"name\":{\"1567\":{},\"1993\":{}},\"comment\":{}}],[\"rightjoin\",{\"_index\":135,\"name\":{\"204\":{},\"297\":{},\"341\":{}},\"comment\":{}}],[\"rightoperand\",{\"_index\":890,\"name\":{\"2131\":{}},\"comment\":{}}],[\"rollbacktransaction\",{\"_index\":481,\"name\":{\"927\":{},\"956\":{},\"1027\":{},\"1181\":{},\"1307\":{}},\"comment\":{}}],[\"rootoperationnode\",{\"_index\":581,\"name\":{\"1455\":{}},\"comment\":{}}],[\"rowcount\",{\"_index\":575,\"name\":{\"1328\":{}},\"comment\":{}}],[\"rows\",{\"_index\":491,\"name\":{\"941\":{},\"1329\":{}},\"comment\":{}}],[\"run\",{\"_index\":538,\"name\":{\"1017\":{}},\"comment\":{}}],[\"sanitizeidentifier\",{\"_index\":381,\"name\":{\"659\":{},\"1032\":{},\"1193\":{},\"1346\":{}},\"comment\":{}}],[\"schema\",{\"_index\":52,\"name\":{\"53\":{},\"84\":{},\"993\":{},\"1624\":{},\"1692\":{}},\"comment\":{}}],[\"schemametadata\",{\"_index\":516,\"name\":{\"985\":{}},\"comment\":{}}],[\"schemamodule\",{\"_index\":390,\"name\":{\"670\":{}},\"comment\":{}}],[\"select\",{\"_index\":121,\"name\":{\"190\":{}},\"comment\":{}}],[\"selectable\",{\"_index\":905,\"name\":{\"2152\":{}},\"comment\":{}}],[\"selectall\",{\"_index\":132,\"name\":{\"201\":{}},\"comment\":{}}],[\"selectallnode\",{\"_index\":856,\"name\":{\"2035\":{}},\"comment\":{}}],[\"selectarg\",{\"_index\":26,\"name\":{\"27\":{}},\"comment\":{}}],[\"selectexpression\",{\"_index\":25,\"name\":{\"26\":{}},\"comment\":{}}],[\"selectfrom\",{\"_index\":2,\"name\":{\"2\":{},\"67\":{},\"90\":{},\"115\":{}},\"comment\":{}}],[\"selection\",{\"_index\":27,\"name\":{\"28\":{},\"2056\":{}},\"comment\":{}}],[\"selectionnode\",{\"_index\":859,\"name\":{\"2054\":{}},\"comment\":{}}],[\"selections\",{\"_index\":855,\"name\":{\"2034\":{},\"2040\":{}},\"comment\":{}}],[\"selectquerybuilder\",{\"_index\":119,\"name\":{\"171\":{}},\"comment\":{}}],[\"selectquerybuilderprops\",{\"_index\":162,\"name\":{\"241\":{}},\"comment\":{}}],[\"selectquerybuilderwithfulljoin\",{\"_index\":169,\"name\":{\"251\":{}},\"comment\":{}}],[\"selectquerybuilderwithinnerjoin\",{\"_index\":166,\"name\":{\"248\":{}},\"comment\":{}}],[\"selectquerybuilderwithleftjoin\",{\"_index\":167,\"name\":{\"249\":{}},\"comment\":{}}],[\"selectquerybuilderwithrightjoin\",{\"_index\":168,\"name\":{\"250\":{}},\"comment\":{}}],[\"selectquerynode\",{\"_index\":857,\"name\":{\"2037\":{}},\"comment\":{}}],[\"selecttype\",{\"_index\":899,\"name\":{\"2146\":{}},\"comment\":{}}],[\"set\",{\"_index\":179,\"name\":{\"299\":{}},\"comment\":{}}],[\"setdatatype\",{\"_index\":469,\"name\":{\"901\":{},\"911\":{}},\"comment\":{}}],[\"setdefault\",{\"_index\":470,\"name\":{\"902\":{},\"912\":{},\"1550\":{}},\"comment\":{}}],[\"setisolationlevel\",{\"_index\":80,\"name\":{\"111\":{}},\"comment\":{}}],[\"setnotnull\",{\"_index\":472,\"name\":{\"904\":{},\"914\":{},\"1552\":{}},\"comment\":{}}],[\"setoperationnode\",{\"_index\":887,\"name\":{\"2122\":{}},\"comment\":{}}],[\"setoperations\",{\"_index\":858,\"name\":{\"2053\":{}},\"comment\":{}}],[\"setoperator\",{\"_index\":886,\"name\":{\"2121\":{}},\"comment\":{}}],[\"setschema\",{\"_index\":451,\"name\":{\"833\":{},\"1560\":{}},\"comment\":{}}],[\"simplereferenceexpression\",{\"_index\":30,\"name\":{\"31\":{}},\"comment\":{}}],[\"simplify\",{\"_index\":22,\"name\":{\"23\":{}},\"comment\":{}}],[\"singleconnectionprovider\",{\"_index\":494,\"name\":{\"947\":{}},\"comment\":{}}],[\"skiplocked\",{\"_index\":130,\"name\":{\"199\":{}},\"comment\":{}}],[\"snakecase\",{\"_index\":635,\"name\":{\"1524\":{}},\"comment\":{}}],[\"sql\",{\"_index\":264,\"name\":{\"506\":{},\"516\":{},\"668\":{}},\"comment\":{}}],[\"sqlbool\",{\"_index\":23,\"name\":{\"24\":{}},\"comment\":{}}],[\"sqlfragments\",{\"_index\":848,\"name\":{\"2014\":{}},\"comment\":{}}],[\"sqliteadapter\",{\"_index\":580,\"name\":{\"1449\":{}},\"comment\":{}}],[\"sqlitedatabase\",{\"_index\":532,\"name\":{\"1011\":{}},\"comment\":{}}],[\"sqlitedialect\",{\"_index\":528,\"name\":{\"1001\":{}},\"comment\":{}}],[\"sqlitedialectconfig\",{\"_index\":529,\"name\":{\"1007\":{}},\"comment\":{}}],[\"sqlitedriver\",{\"_index\":541,\"name\":{\"1021\":{}},\"comment\":{}}],[\"sqliteintrospector\",{\"_index\":579,\"name\":{\"1444\":{}},\"comment\":{}}],[\"sqlitequerycompiler\",{\"_index\":578,\"name\":{\"1338\":{}},\"comment\":{}}],[\"sqlitestatement\",{\"_index\":535,\"name\":{\"1014\":{}},\"comment\":{}}],[\"status\",{\"_index\":608,\"name\":{\"1484\":{}},\"comment\":{}}],[\"stored\",{\"_index\":445,\"name\":{\"814\":{},\"1730\":{}},\"comment\":{}}],[\"stream\",{\"_index\":160,\"name\":{\"239\":{},\"277\":{},\"317\":{},\"362\":{},\"523\":{},\"543\":{},\"557\":{},\"1163\":{},\"2162\":{}},\"comment\":{}}],[\"streamable\",{\"_index\":912,\"name\":{\"2161\":{}},\"comment\":{}}],[\"streamquery\",{\"_index\":487,\"name\":{\"936\":{}},\"comment\":{}}],[\"stringreference\",{\"_index\":31,\"name\":{\"32\":{}},\"comment\":{}}],[\"sum\",{\"_index\":217,\"name\":{\"402\":{}},\"comment\":{}}],[\"supportsreturning\",{\"_index\":502,\"name\":{\"966\":{},\"976\":{},\"1144\":{},\"1298\":{},\"1452\":{}},\"comment\":{}}],[\"supportstransactionalddl\",{\"_index\":501,\"name\":{\"965\":{},\"975\":{},\"1143\":{},\"1297\":{},\"1451\":{}},\"comment\":{}}],[\"table\",{\"_index\":266,\"name\":{\"510\":{},\"1558\":{},\"1607\":{},\"1615\":{},\"1631\":{},\"1686\":{},\"1698\":{},\"1761\":{},\"2018\":{},\"2024\":{},\"2059\":{},\"2067\":{}},\"comment\":{}}],[\"tableexpression\",{\"_index\":36,\"name\":{\"37\":{}},\"comment\":{}}],[\"tableexpressionorlist\",{\"_index\":37,\"name\":{\"38\":{}},\"comment\":{}}],[\"tablemetadata\",{\"_index\":520,\"name\":{\"989\":{}},\"comment\":{}}],[\"tablenode\",{\"_index\":860,\"name\":{\"2057\":{}},\"comment\":{}}],[\"tables\",{\"_index\":519,\"name\":{\"988\":{},\"2138\":{}},\"comment\":{}}],[\"temporary\",{\"_index\":403,\"name\":{\"688\":{},\"871\":{},\"1634\":{},\"1648\":{}},\"comment\":{}}],[\"then\",{\"_index\":253,\"name\":{\"478\":{}},\"comment\":{}}],[\"tooperationnode\",{\"_index\":88,\"name\":{\"132\":{},\"136\":{},\"141\":{},\"144\":{},\"234\":{},\"247\":{},\"272\":{},\"312\":{},\"357\":{},\"390\":{},\"437\":{},\"450\":{},\"465\":{},\"468\":{},\"496\":{},\"501\":{},\"700\":{},\"713\":{},\"727\":{},\"738\":{},\"756\":{},\"769\":{},\"780\":{},\"792\":{},\"818\":{},\"829\":{},\"862\":{},\"878\":{},\"891\":{},\"909\":{},\"1794\":{}},\"comment\":{}}],[\"transaction\",{\"_index\":55,\"name\":{\"58\":{},\"74\":{},\"77\":{}},\"comment\":{}}],[\"transaction_isolation_levels\",{\"_index\":485,\"name\":{\"932\":{}},\"comment\":{}}],[\"transactionbuilder\",{\"_index\":79,\"name\":{\"109\":{}},\"comment\":{}}],[\"transactionsettings\",{\"_index\":483,\"name\":{\"930\":{}},\"comment\":{}}],[\"transformaddcolumn\",{\"_index\":761,\"name\":{\"1821\":{}},\"comment\":{}}],[\"transformaddconstraint\",{\"_index\":793,\"name\":{\"1853\":{}},\"comment\":{}}],[\"transformaggregatefunction\",{\"_index\":805,\"name\":{\"1865\":{}},\"comment\":{}}],[\"transformalias\",{\"_index\":744,\"name\":{\"1804\":{}},\"comment\":{}}],[\"transformaltercolumn\",{\"_index\":791,\"name\":{\"1851\":{}},\"comment\":{}}],[\"transformaltertable\",{\"_index\":788,\"name\":{\"1848\":{}},\"comment\":{}}],[\"transformand\",{\"_index\":748,\"name\":{\"1808\":{}},\"comment\":{}}],[\"transformbinaryoperation\",{\"_index\":809,\"name\":{\"1869\":{}},\"comment\":{}}],[\"transformcase\",{\"_index\":813,\"name\":{\"1873\":{}},\"comment\":{}}],[\"transformcheckconstraint\",{\"_index\":781,\"name\":{\"1841\":{}},\"comment\":{}}],[\"transformcolumn\",{\"_index\":743,\"name\":{\"1803\":{}},\"comment\":{}}],[\"transformcolumndefinition\",{\"_index\":760,\"name\":{\"1820\":{}},\"comment\":{}}],[\"transformcolumnupdate\",{\"_index\":768,\"name\":{\"1828\":{}},\"comment\":{}}],[\"transformcommontableexpression\",{\"_index\":783,\"name\":{\"1843\":{}},\"comment\":{}}],[\"transformcommontableexpressionname\",{\"_index\":784,\"name\":{\"1844\":{}},\"comment\":{}}],[\"transformcreateindex\",{\"_index\":773,\"name\":{\"1833\":{}},\"comment\":{}}],[\"transformcreateschema\",{\"_index\":786,\"name\":{\"1846\":{}},\"comment\":{}}],[\"transformcreatetable\",{\"_index\":759,\"name\":{\"1819\":{}},\"comment\":{}}],[\"transformcreatetype\",{\"_index\":801,\"name\":{\"1861\":{}},\"comment\":{}}],[\"transformcreateview\",{\"_index\":795,\"name\":{\"1855\":{}},\"comment\":{}}],[\"transformdatatype\",{\"_index\":815,\"name\":{\"1875\":{}},\"comment\":{}}],[\"transformdefaultinsertvalue\",{\"_index\":821,\"name\":{\"1881\":{}},\"comment\":{}}],[\"transformdefaultvalue\",{\"_index\":798,\"name\":{\"1858\":{}},\"comment\":{}}],[\"transformdeletequery\",{\"_index\":757,\"name\":{\"1817\":{}},\"comment\":{}}],[\"transformdropcolumn\",{\"_index\":789,\"name\":{\"1849\":{}},\"comment\":{}}],[\"transformdropconstraint\",{\"_index\":794,\"name\":{\"1854\":{}},\"comment\":{}}],[\"transformdropindex\",{\"_index\":775,\"name\":{\"1835\":{}},\"comment\":{}}],[\"transformdropschema\",{\"_index\":787,\"name\":{\"1847\":{}},\"comment\":{}}],[\"transformdroptable\",{\"_index\":762,\"name\":{\"1822\":{}},\"comment\":{}}],[\"transformdroptype\",{\"_index\":802,\"name\":{\"1862\":{}},\"comment\":{}}],[\"transformdropview\",{\"_index\":796,\"name\":{\"1856\":{}},\"comment\":{}}],[\"transformexplain\",{\"_index\":803,\"name\":{\"1863\":{}},\"comment\":{}}],[\"transformforeignkeyconstraint\",{\"_index\":778,\"name\":{\"1838\":{}},\"comment\":{}}],[\"transformfrom\",{\"_index\":746,\"name\":{\"1806\":{}},\"comment\":{}}],[\"transformfunction\",{\"_index\":812,\"name\":{\"1872\":{}},\"comment\":{}}],[\"transformgenerated\",{\"_index\":797,\"name\":{\"1857\":{}},\"comment\":{}}],[\"transformgroupby\",{\"_index\":765,\"name\":{\"1825\":{}},\"comment\":{}}],[\"transformgroupbyitem\",{\"_index\":766,\"name\":{\"1826\":{}},\"comment\":{}}],[\"transformhaving\",{\"_index\":785,\"name\":{\"1845\":{}},\"comment\":{}}],[\"transformidentifier\",{\"_index\":817,\"name\":{\"1877\":{}},\"comment\":{}}],[\"transforminsertquery\",{\"_index\":755,\"name\":{\"1815\":{}},\"comment\":{}}],[\"transformjoin\",{\"_index\":752,\"name\":{\"1812\":{}},\"comment\":{}}],[\"transformlimit\",{\"_index\":769,\"name\":{\"1829\":{}},\"comment\":{}}],[\"transformlist\",{\"_index\":774,\"name\":{\"1834\":{}},\"comment\":{}}],[\"transformmodifycolumn\",{\"_index\":792,\"name\":{\"1852\":{}},\"comment\":{}}],[\"transformnode\",{\"_index\":738,\"name\":{\"1798\":{}},\"comment\":{}}],[\"transformnodeimpl\",{\"_index\":739,\"name\":{\"1799\":{}},\"comment\":{}}],[\"transformnodelist\",{\"_index\":740,\"name\":{\"1800\":{}},\"comment\":{}}],[\"transformoffset\",{\"_index\":770,\"name\":{\"1830\":{}},\"comment\":{}}],[\"transformon\",{\"_index\":799,\"name\":{\"1859\":{}},\"comment\":{}}],[\"transformonconflict\",{\"_index\":771,\"name\":{\"1831\":{}},\"comment\":{}}],[\"transformonduplicatekey\",{\"_index\":772,\"name\":{\"1832\":{}},\"comment\":{}}],[\"transformoperator\",{\"_index\":820,\"name\":{\"1880\":{}},\"comment\":{}}],[\"transformor\",{\"_index\":749,\"name\":{\"1809\":{}},\"comment\":{}}],[\"transformorderby\",{\"_index\":763,\"name\":{\"1823\":{}},\"comment\":{}}],[\"transformorderbyitem\",{\"_index\":764,\"name\":{\"1824\":{}},\"comment\":{}}],[\"transformover\",{\"_index\":806,\"name\":{\"1866\":{}},\"comment\":{}}],[\"transformparens\",{\"_index\":751,\"name\":{\"1811\":{}},\"comment\":{}}],[\"transformpartitionby\",{\"_index\":807,\"name\":{\"1867\":{}},\"comment\":{}}],[\"transformpartitionbyitem\",{\"_index\":808,\"name\":{\"1868\":{}},\"comment\":{}}],[\"transformprimarykeyconstraint\",{\"_index\":776,\"name\":{\"1836\":{}},\"comment\":{}}],[\"transformprimitivevaluelist\",{\"_index\":819,\"name\":{\"1879\":{}},\"comment\":{}}],[\"transformquery\",{\"_index\":274,\"name\":{\"520\":{},\"541\":{},\"555\":{},\"1505\":{},\"1521\":{},\"1528\":{},\"1532\":{}},\"comment\":{}}],[\"transformraw\",{\"_index\":753,\"name\":{\"1813\":{}},\"comment\":{}}],[\"transformreference\",{\"_index\":747,\"name\":{\"1807\":{}},\"comment\":{}}],[\"transformreferences\",{\"_index\":780,\"name\":{\"1840\":{}},\"comment\":{}}],[\"transformrenamecolumn\",{\"_index\":790,\"name\":{\"1850\":{}},\"comment\":{}}],[\"transformresult\",{\"_index\":623,\"name\":{\"1506\":{},\"1522\":{},\"1529\":{},\"1533\":{}},\"comment\":{}}],[\"transformreturning\",{\"_index\":758,\"name\":{\"1818\":{}},\"comment\":{}}],[\"transformschemableidentifier\",{\"_index\":804,\"name\":{\"1864\":{}},\"comment\":{}}],[\"transformselectall\",{\"_index\":816,\"name\":{\"1876\":{}},\"comment\":{}}],[\"transformselection\",{\"_index\":742,\"name\":{\"1802\":{}},\"comment\":{}}],[\"transformselectmodifier\",{\"_index\":800,\"name\":{\"1860\":{}},\"comment\":{}}],[\"transformselectquery\",{\"_index\":741,\"name\":{\"1801\":{}},\"comment\":{}}],[\"transformsetoperation\",{\"_index\":779,\"name\":{\"1839\":{}},\"comment\":{}}],[\"transformtable\",{\"_index\":745,\"name\":{\"1805\":{}},\"comment\":{}}],[\"transformunaryoperation\",{\"_index\":810,\"name\":{\"1870\":{}},\"comment\":{}}],[\"transformuniqueconstraint\",{\"_index\":777,\"name\":{\"1837\":{}},\"comment\":{}}],[\"transformupdatequery\",{\"_index\":767,\"name\":{\"1827\":{}},\"comment\":{}}],[\"transformusing\",{\"_index\":811,\"name\":{\"1871\":{}},\"comment\":{}}],[\"transformvalue\",{\"_index\":818,\"name\":{\"1878\":{}},\"comment\":{}}],[\"transformvaluelist\",{\"_index\":750,\"name\":{\"1810\":{}},\"comment\":{}}],[\"transformvalues\",{\"_index\":756,\"name\":{\"1816\":{}},\"comment\":{}}],[\"transformwhen\",{\"_index\":814,\"name\":{\"1874\":{}},\"comment\":{}}],[\"transformwhere\",{\"_index\":754,\"name\":{\"1814\":{}},\"comment\":{}}],[\"transformwith\",{\"_index\":782,\"name\":{\"1842\":{}},\"comment\":{}}],[\"unary\",{\"_index\":8,\"name\":{\"8\":{}},\"comment\":{}}],[\"unary_filter_operators\",{\"_index\":832,\"name\":{\"1978\":{}},\"comment\":{}}],[\"unary_operators\",{\"_index\":833,\"name\":{\"1979\":{}},\"comment\":{}}],[\"unaryfilteroperator\",{\"_index\":839,\"name\":{\"1985\":{}},\"comment\":{}}],[\"unaryoperationnode\",{\"_index\":891,\"name\":{\"2132\":{}},\"comment\":{}}],[\"unaryoperator\",{\"_index\":838,\"name\":{\"1984\":{}},\"comment\":{}}],[\"underscorebeforedigits\",{\"_index\":629,\"name\":{\"1515\":{}},\"comment\":{}}],[\"underscorebetweenuppercaseletters\",{\"_index\":630,\"name\":{\"1516\":{}},\"comment\":{}}],[\"union\",{\"_index\":143,\"name\":{\"212\":{}},\"comment\":{}}],[\"unionall\",{\"_index\":144,\"name\":{\"213\":{}},\"comment\":{}}],[\"unique\",{\"_index\":424,\"name\":{\"748\":{},\"806\":{},\"1586\":{},\"1617\":{}},\"comment\":{}}],[\"uniqueconstraintnode\",{\"_index\":861,\"name\":{\"2060\":{}},\"comment\":{}}],[\"unknownrow\",{\"_index\":21,\"name\":{\"22\":{}},\"comment\":{}}],[\"unsigned\",{\"_index\":439,\"name\":{\"808\":{},\"1591\":{}},\"comment\":{}}],[\"up\",{\"_index\":588,\"name\":{\"1463\":{}},\"comment\":{}}],[\"updateable\",{\"_index\":907,\"name\":{\"2154\":{}},\"comment\":{}}],[\"updatekeys\",{\"_index\":904,\"name\":{\"2151\":{}},\"comment\":{}}],[\"updateobject\",{\"_index\":42,\"name\":{\"43\":{}},\"comment\":{}}],[\"updatequerybuilder\",{\"_index\":177,\"name\":{\"283\":{}},\"comment\":{}}],[\"updatequerybuilderprops\",{\"_index\":180,\"name\":{\"319\":{}},\"comment\":{}}],[\"updatequerybuilderwithfulljoin\",{\"_index\":184,\"name\":{\"326\":{}},\"comment\":{}}],[\"updatequerybuilderwithinnerjoin\",{\"_index\":181,\"name\":{\"323\":{}},\"comment\":{}}],[\"updatequerybuilderwithleftjoin\",{\"_index\":182,\"name\":{\"324\":{}},\"comment\":{}}],[\"updatequerybuilderwithrightjoin\",{\"_index\":183,\"name\":{\"325\":{}},\"comment\":{}}],[\"updatequerynode\",{\"_index\":863,\"name\":{\"2065\":{}},\"comment\":{}}],[\"updateresult\",{\"_index\":223,\"name\":{\"410\":{}},\"comment\":{}}],[\"updates\",{\"_index\":730,\"name\":{\"1782\":{},\"1788\":{},\"2071\":{}},\"comment\":{}}],[\"updatetable\",{\"_index\":66,\"name\":{\"71\":{},\"94\":{},\"119\":{}},\"comment\":{}}],[\"updatetype\",{\"_index\":901,\"name\":{\"2148\":{}},\"comment\":{}}],[\"updatevaluesnode\",{\"_index\":862,\"name\":{\"2064\":{}},\"comment\":{}}],[\"updatewhere\",{\"_index\":731,\"name\":{\"1783\":{}},\"comment\":{}}],[\"uppercase\",{\"_index\":628,\"name\":{\"1514\":{}},\"comment\":{}}],[\"using\",{\"_index\":186,\"name\":{\"338\":{},\"753\":{},\"1618\":{},\"1665\":{}},\"comment\":{}}],[\"usingnode\",{\"_index\":893,\"name\":{\"2136\":{}},\"comment\":{}}],[\"val\",{\"_index\":5,\"name\":{\"5\":{},\"507\":{}},\"comment\":{}}],[\"value\",{\"_index\":265,\"name\":{\"508\":{},\"1570\":{},\"1600\":{},\"2080\":{}},\"comment\":{}}],[\"valueexpression\",{\"_index\":34,\"name\":{\"35\":{}},\"comment\":{}}],[\"valueexpressionorlist\",{\"_index\":35,\"name\":{\"36\":{}},\"comment\":{}}],[\"valuelistnode\",{\"_index\":864,\"name\":{\"2075\":{}},\"comment\":{}}],[\"valuenode\",{\"_index\":865,\"name\":{\"2078\":{}},\"comment\":{}}],[\"values\",{\"_index\":171,\"name\":{\"254\":{},\"1749\":{},\"2010\":{},\"2077\":{},\"2085\":{}},\"comment\":{}}],[\"valuesitemnode\",{\"_index\":867,\"name\":{\"2082\":{}},\"comment\":{}}],[\"valuesnode\",{\"_index\":868,\"name\":{\"2083\":{}},\"comment\":{}}],[\"visitaddcolumn\",{\"_index\":344,\"name\":{\"622\":{},\"1094\":{},\"1255\":{},\"1408\":{},\"1905\":{}},\"comment\":{}}],[\"visitaddconstraint\",{\"_index\":349,\"name\":{\"627\":{},\"1099\":{},\"1260\":{},\"1413\":{},\"1936\":{}},\"comment\":{}}],[\"visitaggregatefunction\",{\"_index\":361,\"name\":{\"639\":{},\"1111\":{},\"1272\":{},\"1424\":{},\"1957\":{}},\"comment\":{}}],[\"visitalias\",{\"_index\":298,\"name\":{\"576\":{},\"1048\":{},\"1209\":{},\"1363\":{},\"1890\":{}},\"comment\":{}}],[\"visitaltercolumn\",{\"_index\":347,\"name\":{\"625\":{},\"1097\":{},\"1258\":{},\"1411\":{},\"1934\":{}},\"comment\":{}}],[\"visitaltertable\",{\"_index\":343,\"name\":{\"621\":{},\"1093\":{},\"1254\":{},\"1407\":{},\"1931\":{}},\"comment\":{}}],[\"visitand\",{\"_index\":303,\"name\":{\"581\":{},\"1053\":{},\"1214\":{},\"1368\":{},\"1894\":{}},\"comment\":{}}],[\"visitbinaryoperation\",{\"_index\":365,\"name\":{\"643\":{},\"1115\":{},\"1276\":{},\"1428\":{},\"1962\":{}},\"comment\":{}}],[\"visitcase\",{\"_index\":370,\"name\":{\"648\":{},\"1120\":{},\"1281\":{},\"1433\":{},\"1966\":{}},\"comment\":{}}],[\"visitcheckconstraint\",{\"_index\":337,\"name\":{\"615\":{},\"1087\":{},\"1248\":{},\"1401\":{},\"1924\":{}},\"comment\":{}}],[\"visitcolumn\",{\"_index\":289,\"name\":{\"567\":{},\"1039\":{},\"1200\":{},\"1354\":{},\"1889\":{}},\"comment\":{}}],[\"visitcolumndefinition\",{\"_index\":316,\"name\":{\"594\":{},\"1066\":{},\"1227\":{},\"1381\":{},\"1906\":{}},\"comment\":{}}],[\"visitcolumnupdate\",{\"_index\":326,\"name\":{\"604\":{},\"1076\":{},\"1237\":{},\"1390\":{},\"1913\":{}},\"comment\":{}}],[\"visitcommontableexpression\",{\"_index\":341,\"name\":{\"619\":{},\"1091\":{},\"1252\":{},\"1405\":{},\"1926\":{}},\"comment\":{}}],[\"visitcommontableexpressionname\",{\"_index\":342,\"name\":{\"620\":{},\"1092\":{},\"1253\":{},\"1406\":{},\"1927\":{}},\"comment\":{}}],[\"visitcreateindex\",{\"_index\":331,\"name\":{\"609\":{},\"1081\":{},\"1242\":{},\"1395\":{},\"1918\":{}},\"comment\":{}}],[\"visitcreateschema\",{\"_index\":333,\"name\":{\"611\":{},\"1083\":{},\"1244\":{},\"1397\":{},\"1929\":{}},\"comment\":{}}],[\"visitcreatetable\",{\"_index\":315,\"name\":{\"593\":{},\"1065\":{},\"1226\":{},\"1380\":{},\"1904\":{}},\"comment\":{}}],[\"visitcreatetype\",{\"_index\":357,\"name\":{\"635\":{},\"1107\":{},\"1268\":{},\"1421\":{},\"1953\":{}},\"comment\":{}}],[\"visitcreateview\",{\"_index\":352,\"name\":{\"630\":{},\"1102\":{},\"1263\":{},\"1416\":{},\"1946\":{}},\"comment\":{}}],[\"visitdatatype\",{\"_index\":320,\"name\":{\"598\":{},\"1070\":{},\"1231\":{},\"1384\":{},\"1939\":{}},\"comment\":{}}],[\"visitdefaultinsertvalue\",{\"_index\":360,\"name\":{\"638\":{},\"1110\":{},\"1271\":{},\"1347\":{},\"1956\":{}},\"comment\":{}}],[\"visitdefaultvalue\",{\"_index\":355,\"name\":{\"633\":{},\"1105\":{},\"1266\":{},\"1419\":{},\"1949\":{}},\"comment\":{}}],[\"visitdeletequery\",{\"_index\":296,\"name\":{\"574\":{},\"1046\":{},\"1207\":{},\"1361\":{},\"1902\":{}},\"comment\":{}}],[\"visitdropcolumn\",{\"_index\":346,\"name\":{\"624\":{},\"1096\":{},\"1257\":{},\"1410\":{},\"1932\":{}},\"comment\":{}}],[\"visitdropconstraint\",{\"_index\":350,\"name\":{\"628\":{},\"1100\":{},\"1261\":{},\"1414\":{},\"1937\":{}},\"comment\":{}}],[\"visitdropindex\",{\"_index\":332,\"name\":{\"610\":{},\"1082\":{},\"1243\":{},\"1396\":{},\"1919\":{}},\"comment\":{}}],[\"visitdropschema\",{\"_index\":334,\"name\":{\"612\":{},\"1084\":{},\"1245\":{},\"1398\":{},\"1930\":{}},\"comment\":{}}],[\"visitdroptable\",{\"_index\":319,\"name\":{\"597\":{},\"1069\":{},\"1230\":{},\"1383\":{},\"1907\":{}},\"comment\":{}}],[\"visitdroptype\",{\"_index\":358,\"name\":{\"636\":{},\"1108\":{},\"1269\":{},\"1422\":{},\"1954\":{}},\"comment\":{}}],[\"visitdropview\",{\"_index\":353,\"name\":{\"631\":{},\"1103\":{},\"1264\":{},\"1417\":{},\"1947\":{}},\"comment\":{}}],[\"visitexplain\",{\"_index\":359,\"name\":{\"637\":{},\"1109\":{},\"1270\":{},\"1423\":{},\"1955\":{}},\"comment\":{}}],[\"visitforeignkeyconstraint\",{\"_index\":338,\"name\":{\"616\":{},\"1088\":{},\"1249\":{},\"1402\":{},\"1938\":{}},\"comment\":{}}],[\"visitfrom\",{\"_index\":287,\"name\":{\"565\":{},\"1037\":{},\"1198\":{},\"1352\":{},\"1892\":{}},\"comment\":{}}],[\"visitfunction\",{\"_index\":369,\"name\":{\"647\":{},\"1119\":{},\"1280\":{},\"1432\":{},\"1965\":{}},\"comment\":{}}],[\"visitgenerated\",{\"_index\":354,\"name\":{\"632\":{},\"1104\":{},\"1265\":{},\"1418\":{},\"1948\":{}},\"comment\":{}}],[\"visitgroupby\",{\"_index\":323,\"name\":{\"601\":{},\"1073\":{},\"1234\":{},\"1387\":{},\"1910\":{}},\"comment\":{}}],[\"visitgroupbyitem\",{\"_index\":324,\"name\":{\"602\":{},\"1074\":{},\"1235\":{},\"1388\":{},\"1911\":{}},\"comment\":{}}],[\"visithaving\",{\"_index\":293,\"name\":{\"571\":{},\"1043\":{},\"1204\":{},\"1358\":{},\"1928\":{}},\"comment\":{}}],[\"visitidentifier\",{\"_index\":301,\"name\":{\"579\":{},\"1051\":{},\"1212\":{},\"1366\":{},\"1941\":{}},\"comment\":{}}],[\"visitinsertquery\",{\"_index\":294,\"name\":{\"572\":{},\"1044\":{},\"1205\":{},\"1359\":{},\"1901\":{}},\"comment\":{}}],[\"visitjoin\",{\"_index\":309,\"name\":{\"587\":{},\"1059\":{},\"1220\":{},\"1374\":{},\"1898\":{}},\"comment\":{}}],[\"visitlimit\",{\"_index\":327,\"name\":{\"605\":{},\"1077\":{},\"1238\":{},\"1391\":{},\"1914\":{}},\"comment\":{}}],[\"visitlist\",{\"_index\":339,\"name\":{\"617\":{},\"1089\":{},\"1250\":{},\"1403\":{},\"1920\":{}},\"comment\":{}}],[\"visitmodifycolumn\",{\"_index\":348,\"name\":{\"626\":{},\"1098\":{},\"1259\":{},\"1412\":{},\"1935\":{}},\"comment\":{}}],[\"visitnode\",{\"_index\":386,\"name\":{\"664\":{},\"1135\":{},\"1289\":{},\"1443\":{},\"1886\":{}},\"comment\":{}}],[\"visitoffset\",{\"_index\":328,\"name\":{\"606\":{},\"1078\":{},\"1239\":{},\"1392\":{},\"1915\":{}},\"comment\":{}}],[\"visiton\",{\"_index\":310,\"name\":{\"588\":{},\"1060\":{},\"1221\":{},\"1375\":{},\"1950\":{}},\"comment\":{}}],[\"visitonconflict\",{\"_index\":329,\"name\":{\"607\":{},\"1079\":{},\"1240\":{},\"1393\":{},\"1916\":{}},\"comment\":{}}],[\"visitonduplicatekey\",{\"_index\":330,\"name\":{\"608\":{},\"1080\":{},\"1241\":{},\"1394\":{},\"1917\":{}},\"comment\":{}}],[\"visitoperator\",{\"_index\":312,\"name\":{\"590\":{},\"1062\":{},\"1223\":{},\"1377\":{},\"1945\":{}},\"comment\":{}}],[\"visitor\",{\"_index\":304,\"name\":{\"582\":{},\"1054\":{},\"1215\":{},\"1369\":{},\"1895\":{}},\"comment\":{}}],[\"visitorderby\",{\"_index\":321,\"name\":{\"599\":{},\"1071\":{},\"1232\":{},\"1385\":{},\"1908\":{}},\"comment\":{}}],[\"visitorderbyitem\",{\"_index\":322,\"name\":{\"600\":{},\"1072\":{},\"1233\":{},\"1386\":{},\"1909\":{}},\"comment\":{}}],[\"visitover\",{\"_index\":362,\"name\":{\"640\":{},\"1112\":{},\"1273\":{},\"1425\":{},\"1958\":{}},\"comment\":{}}],[\"visitparens\",{\"_index\":308,\"name\":{\"586\":{},\"1058\":{},\"1219\":{},\"1373\":{},\"1897\":{}},\"comment\":{}}],[\"visitpartitionby\",{\"_index\":363,\"name\":{\"641\":{},\"1113\":{},\"1274\":{},\"1426\":{},\"1959\":{}},\"comment\":{}}],[\"visitpartitionbyitem\",{\"_index\":364,\"name\":{\"642\":{},\"1114\":{},\"1275\":{},\"1427\":{},\"1960\":{}},\"comment\":{}}],[\"visitprimarykeyconstraint\",{\"_index\":335,\"name\":{\"613\":{},\"1085\":{},\"1246\":{},\"1399\":{},\"1921\":{}},\"comment\":{}}],[\"visitprimitivevaluelist\",{\"_index\":307,\"name\":{\"585\":{},\"1057\":{},\"1218\":{},\"1372\":{},\"1944\":{}},\"comment\":{}}],[\"visitraw\",{\"_index\":311,\"name\":{\"589\":{},\"1061\":{},\"1222\":{},\"1376\":{},\"1899\":{}},\"comment\":{}}],[\"visitreference\",{\"_index\":299,\"name\":{\"577\":{},\"1049\":{},\"1210\":{},\"1364\":{},\"1893\":{}},\"comment\":{}}],[\"visitreferences\",{\"_index\":318,\"name\":{\"596\":{},\"1068\":{},\"1229\":{},\"1382\":{},\"1923\":{}},\"comment\":{}}],[\"visitrenamecolumn\",{\"_index\":345,\"name\":{\"623\":{},\"1095\":{},\"1256\":{},\"1409\":{},\"1933\":{}},\"comment\":{}}],[\"visitreturning\",{\"_index\":297,\"name\":{\"575\":{},\"1047\":{},\"1208\":{},\"1362\":{},\"1903\":{}},\"comment\":{}}],[\"visitschemableidentifier\",{\"_index\":314,\"name\":{\"592\":{},\"1064\":{},\"1225\":{},\"1379\":{},\"1942\":{}},\"comment\":{}}],[\"visitselectall\",{\"_index\":300,\"name\":{\"578\":{},\"1050\":{},\"1211\":{},\"1365\":{},\"1940\":{}},\"comment\":{}}],[\"visitselection\",{\"_index\":288,\"name\":{\"566\":{},\"1038\":{},\"1199\":{},\"1353\":{},\"1888\":{}},\"comment\":{}}],[\"visitselectmodifier\",{\"_index\":356,\"name\":{\"634\":{},\"1106\":{},\"1267\":{},\"1420\":{},\"1952\":{}},\"comment\":{}}],[\"visitselectquery\",{\"_index\":286,\"name\":{\"564\":{},\"1036\":{},\"1197\":{},\"1351\":{},\"1887\":{}},\"comment\":{}}],[\"visitsetoperation\",{\"_index\":351,\"name\":{\"629\":{},\"1101\":{},\"1262\":{},\"1415\":{},\"1961\":{}},\"comment\":{}}],[\"visittable\",{\"_index\":313,\"name\":{\"591\":{},\"1063\":{},\"1224\":{},\"1378\":{},\"1891\":{}},\"comment\":{}}],[\"visitunaryoperation\",{\"_index\":366,\"name\":{\"644\":{},\"1116\":{},\"1277\":{},\"1429\":{},\"1963\":{}},\"comment\":{}}],[\"visituniqueconstraint\",{\"_index\":336,\"name\":{\"614\":{},\"1086\":{},\"1247\":{},\"1400\":{},\"1922\":{}},\"comment\":{}}],[\"visitupdatequery\",{\"_index\":325,\"name\":{\"603\":{},\"1075\":{},\"1236\":{},\"1389\":{},\"1912\":{}},\"comment\":{}}],[\"visitusing\",{\"_index\":368,\"name\":{\"646\":{},\"1118\":{},\"1279\":{},\"1431\":{},\"1964\":{}},\"comment\":{}}],[\"visitvalue\",{\"_index\":305,\"name\":{\"583\":{},\"1055\":{},\"1216\":{},\"1370\":{},\"1943\":{}},\"comment\":{}}],[\"visitvaluelist\",{\"_index\":306,\"name\":{\"584\":{},\"1056\":{},\"1217\":{},\"1371\":{},\"1896\":{}},\"comment\":{}}],[\"visitvalues\",{\"_index\":295,\"name\":{\"573\":{},\"1045\":{},\"1206\":{},\"1360\":{},\"1951\":{}},\"comment\":{}}],[\"visitwhen\",{\"_index\":371,\"name\":{\"649\":{},\"1121\":{},\"1282\":{},\"1434\":{},\"1967\":{}},\"comment\":{}}],[\"visitwhere\",{\"_index\":292,\"name\":{\"570\":{},\"1042\":{},\"1203\":{},\"1357\":{},\"1900\":{}},\"comment\":{}}],[\"visitwith\",{\"_index\":340,\"name\":{\"618\":{},\"1090\":{},\"1251\":{},\"1404\":{},\"1925\":{}},\"comment\":{}}],[\"when\",{\"_index\":251,\"name\":{\"475\":{},\"481\":{},\"1571\":{}},\"comment\":{}}],[\"whennode\",{\"_index\":869,\"name\":{\"2086\":{}},\"comment\":{}}],[\"where\",{\"_index\":96,\"name\":{\"146\":{},\"173\":{},\"285\":{},\"329\":{},\"419\":{},\"440\":{},\"754\":{},\"1620\":{},\"1667\":{},\"2045\":{},\"2070\":{},\"2092\":{}},\"comment\":{}}],[\"whereexists\",{\"_index\":100,\"name\":{\"150\":{},\"177\":{},\"289\":{},\"333\":{},\"423\":{},\"444\":{}},\"comment\":{}}],[\"whereexpressionfactory\",{\"_index\":105,\"name\":{\"155\":{}},\"comment\":{}}],[\"whereinterface\",{\"_index\":95,\"name\":{\"145\":{}},\"comment\":{}}],[\"wherenode\",{\"_index\":871,\"name\":{\"2090\":{}},\"comment\":{}}],[\"wherenotexists\",{\"_index\":101,\"name\":{\"151\":{},\"178\":{},\"290\":{},\"334\":{},\"424\":{},\"445\":{}},\"comment\":{}}],[\"whereref\",{\"_index\":97,\"name\":{\"147\":{},\"174\":{},\"286\":{},\"330\":{},\"420\":{},\"441\":{}},\"comment\":{}}],[\"with\",{\"_index\":67,\"name\":{\"72\":{},\"95\":{},\"120\":{},\"1669\":{},\"1753\":{},\"2050\":{},\"2073\":{}},\"comment\":{}}],[\"withconnectionprovider\",{\"_index\":276,\"name\":{\"524\":{},\"538\":{},\"549\":{}},\"comment\":{}}],[\"withinternalkyselytables\",{\"_index\":515,\"name\":{\"984\":{}},\"comment\":{}}],[\"withnode\",{\"_index\":83,\"name\":{\"127\":{},\"2094\":{}},\"comment\":{}}],[\"withnodeparams\",{\"_index\":872,\"name\":{\"2093\":{}},\"comment\":{}}],[\"withoutplugins\",{\"_index\":58,\"name\":{\"61\":{},\"81\":{},\"123\":{},\"528\":{},\"539\":{},\"553\":{},\"684\":{}},\"comment\":{}}],[\"withplugin\",{\"_index\":57,\"name\":{\"60\":{},\"80\":{},\"122\":{},\"233\":{},\"271\":{},\"311\":{},\"356\":{},\"495\":{},\"525\":{},\"536\":{},\"550\":{},\"683\":{}},\"comment\":{}}],[\"withpluginatfront\",{\"_index\":278,\"name\":{\"527\":{},\"537\":{},\"552\":{}},\"comment\":{}}],[\"withplugins\",{\"_index\":277,\"name\":{\"526\":{},\"535\":{},\"551\":{}},\"comment\":{}}],[\"withrecursive\",{\"_index\":68,\"name\":{\"73\":{},\"96\":{},\"121\":{}},\"comment\":{}}],[\"withschema\",{\"_index\":14,\"name\":{\"14\":{},\"62\":{},\"82\":{},\"124\":{},\"685\":{}},\"comment\":{}}],[\"withschemaplugin\",{\"_index\":638,\"name\":{\"1530\":{}},\"comment\":{}}],[\"withtables\",{\"_index\":59,\"name\":{\"63\":{},\"83\":{}},\"comment\":{}}]],\"pipeline\":[]}}"); \ No newline at end of file diff --git a/docs/assets/style.css b/docs/assets/style.css deleted file mode 100644 index 496e66f21..000000000 --- a/docs/assets/style.css +++ /dev/null @@ -1,1279 +0,0 @@ -:root { - /* Light */ - --light-color-background: #f2f4f8; - --light-color-background-secondary: #eff0f1; - --light-color-warning-text: #222; - --light-color-background-warning: #e6e600; - --light-color-icon-background: var(--light-color-background); - --light-color-accent: #c5c7c9; - --light-color-text: #222; - --light-color-text-aside: #707070; - --light-color-link: #4da6ff; - --light-color-ts: #db1373; - --light-color-ts-interface: #139d2c; - --light-color-ts-enum: #9c891a; - --light-color-ts-class: #2484e5; - --light-color-ts-function: #572be7; - --light-color-ts-namespace: #b111c9; - --light-color-ts-private: #707070; - --light-color-ts-variable: #4d68ff; - --light-external-icon: url("data:image/svg+xml;utf8,"); - --light-color-scheme: light; - - /* Dark */ - --dark-color-background: #2b2e33; - --dark-color-background-secondary: #1e2024; - --dark-color-background-warning: #bebe00; - --dark-color-warning-text: #222; - --dark-color-icon-background: var(--dark-color-background-secondary); - --dark-color-accent: #9096a2; - --dark-color-text: #f5f5f5; - --dark-color-text-aside: #dddddd; - --dark-color-link: #00aff4; - --dark-color-ts: #ff6492; - --dark-color-ts-interface: #6cff87; - --dark-color-ts-enum: #f4d93e; - --dark-color-ts-class: #61b0ff; - --dark-color-ts-function: #9772ff; - --dark-color-ts-namespace: #e14dff; - --dark-color-ts-private: #e2e2e2; - --dark-color-ts-variable: #4d68ff; - --dark-external-icon: url("data:image/svg+xml;utf8,"); - --dark-color-scheme: dark; -} - -@media (prefers-color-scheme: light) { - :root { - --color-background: var(--light-color-background); - --color-background-secondary: var(--light-color-background-secondary); - --color-background-warning: var(--light-color-background-warning); - --color-warning-text: var(--light-color-warning-text); - --color-icon-background: var(--light-color-icon-background); - --color-accent: var(--light-color-accent); - --color-text: var(--light-color-text); - --color-text-aside: var(--light-color-text-aside); - --color-link: var(--light-color-link); - --color-ts: var(--light-color-ts); - --color-ts-interface: var(--light-color-ts-interface); - --color-ts-enum: var(--light-color-ts-enum); - --color-ts-class: var(--light-color-ts-class); - --color-ts-function: var(--light-color-ts-function); - --color-ts-namespace: var(--light-color-ts-namespace); - --color-ts-private: var(--light-color-ts-private); - --color-ts-variable: var(--light-color-ts-variable); - --external-icon: var(--light-external-icon); - --color-scheme: var(--light-color-scheme); - } -} - -@media (prefers-color-scheme: dark) { - :root { - --color-background: var(--dark-color-background); - --color-background-secondary: var(--dark-color-background-secondary); - --color-background-warning: var(--dark-color-background-warning); - --color-warning-text: var(--dark-color-warning-text); - --color-icon-background: var(--dark-color-icon-background); - --color-accent: var(--dark-color-accent); - --color-text: var(--dark-color-text); - --color-text-aside: var(--dark-color-text-aside); - --color-link: var(--dark-color-link); - --color-ts: var(--dark-color-ts); - --color-ts-interface: var(--dark-color-ts-interface); - --color-ts-enum: var(--dark-color-ts-enum); - --color-ts-class: var(--dark-color-ts-class); - --color-ts-function: var(--dark-color-ts-function); - --color-ts-namespace: var(--dark-color-ts-namespace); - --color-ts-private: var(--dark-color-ts-private); - --color-ts-variable: var(--dark-color-ts-variable); - --external-icon: var(--dark-external-icon); - --color-scheme: var(--dark-color-scheme); - } -} - -html { - color-scheme: var(--color-scheme); -} - -body { - margin: 0; -} - -:root[data-theme="light"] { - --color-background: var(--light-color-background); - --color-background-secondary: var(--light-color-background-secondary); - --color-background-warning: var(--light-color-background-warning); - --color-warning-text: var(--light-color-warning-text); - --color-icon-background: var(--light-color-icon-background); - --color-accent: var(--light-color-accent); - --color-text: var(--light-color-text); - --color-text-aside: var(--light-color-text-aside); - --color-link: var(--light-color-link); - --color-ts: var(--light-color-ts); - --color-ts-interface: var(--light-color-ts-interface); - --color-ts-enum: var(--light-color-ts-enum); - --color-ts-class: var(--light-color-ts-class); - --color-ts-function: var(--light-color-ts-function); - --color-ts-namespace: var(--light-color-ts-namespace); - --color-ts-private: var(--light-color-ts-private); - --color-ts-variable: var(--light-color-ts-variable); - --external-icon: var(--light-external-icon); - --color-scheme: var(--light-color-scheme); -} - -:root[data-theme="dark"] { - --color-background: var(--dark-color-background); - --color-background-secondary: var(--dark-color-background-secondary); - --color-background-warning: var(--dark-color-background-warning); - --color-warning-text: var(--dark-color-warning-text); - --color-icon-background: var(--dark-color-icon-background); - --color-accent: var(--dark-color-accent); - --color-text: var(--dark-color-text); - --color-text-aside: var(--dark-color-text-aside); - --color-link: var(--dark-color-link); - --color-ts: var(--dark-color-ts); - --color-ts-interface: var(--dark-color-ts-interface); - --color-ts-enum: var(--dark-color-ts-enum); - --color-ts-class: var(--dark-color-ts-class); - --color-ts-function: var(--dark-color-ts-function); - --color-ts-namespace: var(--dark-color-ts-namespace); - --color-ts-private: var(--dark-color-ts-private); - --color-ts-variable: var(--dark-color-ts-variable); - --external-icon: var(--dark-external-icon); - --color-scheme: var(--dark-color-scheme); -} - -.always-visible, -.always-visible .tsd-signatures { - display: inherit !important; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - line-height: 1.2; -} - -h1 { - font-size: 1.875rem; - margin: 0.67rem 0; -} - -h2 { - font-size: 1.5rem; - margin: 0.83rem 0; -} - -h3 { - font-size: 1.25rem; - margin: 1rem 0; -} - -h4 { - font-size: 1.05rem; - margin: 1.33rem 0; -} - -h5 { - font-size: 1rem; - margin: 1.5rem 0; -} - -h6 { - font-size: 0.875rem; - margin: 2.33rem 0; -} - -.uppercase { - text-transform: uppercase; -} - -pre { - white-space: pre; - white-space: pre-wrap; - word-wrap: break-word; -} - -dl, -menu, -ol, -ul { - margin: 1em 0; -} - -dd { - margin: 0 0 0 40px; -} - -.container { - max-width: 1600px; - padding: 0 2rem; -} - -@media (min-width: 640px) { - .container { - padding: 0 4rem; - } -} -@media (min-width: 1200px) { - .container { - padding: 0 8rem; - } -} -@media (min-width: 1600px) { - .container { - padding: 0 12rem; - } -} - -/* Footer */ -.tsd-generator { - border-top: 1px solid var(--color-accent); - padding-top: 1rem; - padding-bottom: 1rem; - max-height: 3.5rem; -} - -.tsd-generator > p { - margin-top: 0; - margin-bottom: 0; - padding: 0 1rem; -} - -.container-main { - display: flex; - justify-content: space-between; - position: relative; - margin: 0 auto; -} - -.col-4, -.col-8 { - box-sizing: border-box; - float: left; - padding: 2rem 1rem; -} - -.col-4 { - flex: 0 0 25%; -} -.col-8 { - flex: 1 0; - flex-wrap: wrap; - padding-left: 0; -} - -@keyframes fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } -} -@keyframes fade-out { - from { - opacity: 1; - visibility: visible; - } - to { - opacity: 0; - } -} -@keyframes fade-in-delayed { - 0% { - opacity: 0; - } - 33% { - opacity: 0; - } - 100% { - opacity: 1; - } -} -@keyframes fade-out-delayed { - 0% { - opacity: 1; - visibility: visible; - } - 66% { - opacity: 0; - } - 100% { - opacity: 0; - } -} -@keyframes shift-to-left { - from { - transform: translate(0, 0); - } - to { - transform: translate(-25%, 0); - } -} -@keyframes unshift-to-left { - from { - transform: translate(-25%, 0); - } - to { - transform: translate(0, 0); - } -} -@keyframes pop-in-from-right { - from { - transform: translate(100%, 0); - } - to { - transform: translate(0, 0); - } -} -@keyframes pop-out-to-right { - from { - transform: translate(0, 0); - visibility: visible; - } - to { - transform: translate(100%, 0); - } -} -body { - background: var(--color-background); - font-family: "Segoe UI", sans-serif; - font-size: 16px; - color: var(--color-text); -} - -a { - color: var(--color-link); - text-decoration: none; -} -a:hover { - text-decoration: underline; -} -a.external[target="_blank"] { - background-image: var(--external-icon); - background-position: top 3px right; - background-repeat: no-repeat; - padding-right: 13px; -} - -code, -pre { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - padding: 0.2em; - margin: 0; - font-size: 0.875rem; - border-radius: 0.8em; -} - -pre { - padding: 10px; - border: 0.1em solid var(--color-accent); -} -pre code { - padding: 0; - font-size: 100%; -} - -blockquote { - margin: 1em 0; - padding-left: 1em; - border-left: 4px solid gray; -} - -.tsd-typography { - line-height: 1.333em; -} -.tsd-typography ul { - list-style: square; - padding: 0 0 0 20px; - margin: 0; -} -.tsd-typography h4, -.tsd-typography .tsd-index-panel h3, -.tsd-index-panel .tsd-typography h3, -.tsd-typography h5, -.tsd-typography h6 { - font-size: 1em; - margin: 0; -} -.tsd-typography h5, -.tsd-typography h6 { - font-weight: normal; -} -.tsd-typography p, -.tsd-typography ul, -.tsd-typography ol { - margin: 1em 0; -} - -@media (max-width: 1024px) { - html .col-content { - float: none; - max-width: 100%; - width: 100%; - padding-top: 3rem; - } - html .col-menu { - position: fixed !important; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - z-index: 1024; - top: 0 !important; - bottom: 0 !important; - left: auto !important; - right: 0 !important; - padding: 1.5rem 1.5rem 0 0; - max-width: 25rem; - visibility: hidden; - background-color: var(--color-background); - transform: translate(100%, 0); - } - html .col-menu > *:last-child { - padding-bottom: 20px; - } - html .overlay { - content: ""; - display: block; - position: fixed; - z-index: 1023; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.75); - visibility: hidden; - } - - .to-has-menu .overlay { - animation: fade-in 0.4s; - } - - .to-has-menu :is(header, footer, .col-content) { - animation: shift-to-left 0.4s; - } - - .to-has-menu .col-menu { - animation: pop-in-from-right 0.4s; - } - - .from-has-menu .overlay { - animation: fade-out 0.4s; - } - - .from-has-menu :is(header, footer, .col-content) { - animation: unshift-to-left 0.4s; - } - - .from-has-menu .col-menu { - animation: pop-out-to-right 0.4s; - } - - .has-menu body { - overflow: hidden; - } - .has-menu .overlay { - visibility: visible; - } - .has-menu :is(header, footer, .col-content) { - transform: translate(-25%, 0); - } - .has-menu .col-menu { - visibility: visible; - transform: translate(0, 0); - display: flex; - flex-direction: column; - gap: 1.5rem; - max-height: 100vh; - padding: 1rem 2rem; - } - .has-menu .tsd-navigation { - max-height: 100%; - } -} - -.tsd-breadcrumb { - margin: 0; - padding: 0; - color: var(--color-text-aside); -} -.tsd-breadcrumb a { - color: var(--color-text-aside); - text-decoration: none; -} -.tsd-breadcrumb a:hover { - text-decoration: underline; -} -.tsd-breadcrumb li { - display: inline; -} -.tsd-breadcrumb li:after { - content: " / "; -} - -.tsd-comment-tags { - display: flex; - flex-direction: column; -} -dl.tsd-comment-tag-group { - display: flex; - align-items: center; - overflow: hidden; - margin: 0.5em 0; -} -dl.tsd-comment-tag-group dt { - display: flex; - margin-right: 0.5em; - font-size: 0.875em; - font-weight: normal; -} -dl.tsd-comment-tag-group dd { - margin: 0; -} -code.tsd-tag { - padding: 0.25em 0.4em; - border: 0.1em solid var(--color-accent); - margin-right: 0.25em; - font-size: 70%; -} -h1 code.tsd-tag:first-of-type { - margin-left: 0.25em; -} - -dl.tsd-comment-tag-group dd:before, -dl.tsd-comment-tag-group dd:after { - content: " "; -} -dl.tsd-comment-tag-group dd pre, -dl.tsd-comment-tag-group dd:after { - clear: both; -} -dl.tsd-comment-tag-group p { - margin: 0; -} - -.tsd-panel.tsd-comment .lead { - font-size: 1.1em; - line-height: 1.333em; - margin-bottom: 2em; -} -.tsd-panel.tsd-comment .lead:last-child { - margin-bottom: 0; -} - -.tsd-filter-visibility h4 { - font-size: 1rem; - padding-top: 0.75rem; - padding-bottom: 0.5rem; - margin: 0; -} -.tsd-filter-item:not(:last-child) { - margin-bottom: 0.5rem; -} -.tsd-filter-input { - display: flex; - width: fit-content; - width: -moz-fit-content; - align-items: center; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - cursor: pointer; -} -.tsd-filter-input input[type="checkbox"] { - cursor: pointer; - position: absolute; - width: 1.5em; - height: 1.5em; - opacity: 0; -} -.tsd-filter-input input[type="checkbox"]:disabled { - pointer-events: none; -} -.tsd-filter-input svg { - cursor: pointer; - width: 1.5em; - height: 1.5em; - margin-right: 0.5em; - border-radius: 0.33em; - /* Leaving this at full opacity breaks event listeners on Firefox. - Don't remove unless you know what you're doing. */ - opacity: 0.99; -} -.tsd-filter-input input[type="checkbox"]:focus + svg { - transform: scale(0.95); -} -.tsd-filter-input input[type="checkbox"]:focus:not(:focus-visible) + svg { - transform: scale(1); -} -.tsd-checkbox-background { - fill: var(--color-accent); -} -input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { - stroke: var(--color-text); -} -.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-background { - fill: var(--color-background); - stroke: var(--color-accent); - stroke-width: 0.25rem; -} -.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-checkmark { - stroke: var(--color-accent); -} - -.tsd-theme-toggle { - padding-top: 0.75rem; -} -.tsd-theme-toggle > h4 { - display: inline; - vertical-align: middle; - margin-right: 0.75rem; -} - -.tsd-hierarchy { - list-style: square; - margin: 0; -} -.tsd-hierarchy .target { - font-weight: bold; -} - -.tsd-panel-group.tsd-index-group { - margin-bottom: 0; -} -.tsd-index-panel .tsd-index-list { - list-style: none; - line-height: 1.333em; - margin: 0; - padding: 0.25rem 0 0 0; - overflow: hidden; - display: grid; - grid-template-columns: repeat(3, 1fr); - column-gap: 1rem; - grid-template-rows: auto; -} -@media (max-width: 1024px) { - .tsd-index-panel .tsd-index-list { - grid-template-columns: repeat(2, 1fr); - } -} -@media (max-width: 768px) { - .tsd-index-panel .tsd-index-list { - grid-template-columns: repeat(1, 1fr); - } -} -.tsd-index-panel .tsd-index-list li { - -webkit-page-break-inside: avoid; - -moz-page-break-inside: avoid; - -ms-page-break-inside: avoid; - -o-page-break-inside: avoid; - page-break-inside: avoid; -} -.tsd-index-panel a, -.tsd-index-panel a.tsd-parent-kind-module { - color: var(--color-ts); -} -.tsd-index-panel a.tsd-parent-kind-interface { - color: var(--color-ts-interface); -} -.tsd-index-panel a.tsd-parent-kind-enum { - color: var(--color-ts-enum); -} -.tsd-index-panel a.tsd-parent-kind-class { - color: var(--color-ts-class); -} -.tsd-index-panel a.tsd-kind-module { - color: var(--color-ts-namespace); -} -.tsd-index-panel a.tsd-kind-interface { - color: var(--color-ts-interface); -} -.tsd-index-panel a.tsd-kind-enum { - color: var(--color-ts-enum); -} -.tsd-index-panel a.tsd-kind-class { - color: var(--color-ts-class); -} -.tsd-index-panel a.tsd-kind-function { - color: var(--color-ts-function); -} -.tsd-index-panel a.tsd-kind-namespace { - color: var(--color-ts-namespace); -} -.tsd-index-panel a.tsd-kind-variable { - color: var(--color-ts-variable); -} -.tsd-index-panel a.tsd-is-private { - color: var(--color-ts-private); -} - -.tsd-flag { - display: inline-block; - padding: 0.25em 0.4em; - border-radius: 4px; - color: var(--color-comment-tag-text); - background-color: var(--color-comment-tag); - text-indent: 0; - font-size: 75%; - line-height: 1; - font-weight: normal; -} - -.tsd-anchor { - position: absolute; - top: -100px; -} - -.tsd-member { - position: relative; -} -.tsd-member .tsd-anchor + h3 { - display: flex; - align-items: center; - margin-top: 0; - margin-bottom: 0; - border-bottom: none; -} -.tsd-member [data-tsd-kind] { - color: var(--color-ts); -} -.tsd-member [data-tsd-kind="Interface"] { - color: var(--color-ts-interface); -} -.tsd-member [data-tsd-kind="Enum"] { - color: var(--color-ts-enum); -} -.tsd-member [data-tsd-kind="Class"] { - color: var(--color-ts-class); -} -.tsd-member [data-tsd-kind="Private"] { - color: var(--color-ts-private); -} - -.tsd-navigation a { - display: block; - margin: 0.4rem 0; - border-left: 2px solid transparent; - color: var(--color-text); - text-decoration: none; - transition: border-left-color 0.1s; -} -.tsd-navigation a:hover { - text-decoration: underline; -} -.tsd-navigation ul { - margin: 0; - padding: 0; - list-style: none; -} -.tsd-navigation li { - padding: 0; -} - -.tsd-navigation.primary .tsd-accordion-details > ul { - margin-top: 0.75rem; -} -.tsd-navigation.primary a { - padding: 0.75rem 0.5rem; - margin: 0; -} -.tsd-navigation.primary ul li a { - margin-left: 0.5rem; -} -.tsd-navigation.primary ul li li a { - margin-left: 1.5rem; -} -.tsd-navigation.primary ul li li li a { - margin-left: 2.5rem; -} -.tsd-navigation.primary ul li li li li a { - margin-left: 3.5rem; -} -.tsd-navigation.primary ul li li li li li a { - margin-left: 4.5rem; -} -.tsd-navigation.primary ul li li li li li li a { - margin-left: 5.5rem; -} -.tsd-navigation.primary li.current > a { - border-left: 0.15rem var(--color-text) solid; -} -.tsd-navigation.primary li.selected > a { - font-weight: bold; - border-left: 0.2rem var(--color-text) solid; -} -.tsd-navigation.primary ul li a:hover { - border-left: 0.2rem var(--color-text-aside) solid; -} -.tsd-navigation.primary li.globals + li > span, -.tsd-navigation.primary li.globals + li > a { - padding-top: 20px; -} - -.tsd-navigation.secondary.tsd-navigation--toolbar-hide { - max-height: calc(100vh - 1rem); - top: 0.5rem; -} -.tsd-navigation.secondary > ul { - display: inline; - padding-right: 0.5rem; - transition: opacity 0.2s; -} -.tsd-navigation.secondary ul li a { - padding-left: 0; -} -.tsd-navigation.secondary ul li li a { - padding-left: 1.1rem; -} -.tsd-navigation.secondary ul li li li a { - padding-left: 2.2rem; -} -.tsd-navigation.secondary ul li li li li a { - padding-left: 3.3rem; -} -.tsd-navigation.secondary ul li li li li li a { - padding-left: 4.4rem; -} -.tsd-navigation.secondary ul li li li li li li a { - padding-left: 5.5rem; -} - -#tsd-sidebar-links a { - margin-top: 0; - margin-bottom: 0.5rem; - line-height: 1.25rem; -} -#tsd-sidebar-links a:last-of-type { - margin-bottom: 0; -} - -a.tsd-index-link { - margin: 0.25rem 0; - font-size: 1rem; - line-height: 1.25rem; - display: inline-flex; - align-items: center; -} -.tsd-accordion-summary > h1, -.tsd-accordion-summary > h2, -.tsd-accordion-summary > h3, -.tsd-accordion-summary > h4, -.tsd-accordion-summary > h5 { - display: inline-flex; - align-items: center; - vertical-align: middle; - margin-bottom: 0; - user-select: none; - -moz-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; -} -.tsd-accordion-summary { - display: block; - cursor: pointer; -} -.tsd-accordion-summary > * { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; -} -.tsd-accordion-summary::-webkit-details-marker { - display: none; -} -.tsd-index-accordion .tsd-accordion-summary svg { - margin-right: 0.25rem; -} -.tsd-index-content > :not(:first-child) { - margin-top: 0.75rem; -} -.tsd-index-heading { - margin-top: 1.5rem; - margin-bottom: 0.75rem; -} - -.tsd-kind-icon { - margin-right: 0.5rem; - width: 1.25rem; - height: 1.25rem; - min-width: 1.25rem; - min-height: 1.25rem; -} -.tsd-kind-icon path { - transform-origin: center; - transform: scale(1.1); -} -.tsd-signature > .tsd-kind-icon { - margin-right: 0.8rem; -} - -@media (min-width: 1025px) { - .col-content { - margin: 2rem auto; - } - - .menu-sticky-wrap { - position: sticky; - height: calc(100vh - 2rem); - top: 4rem; - right: 0; - padding: 0 1.5rem; - padding-top: 1rem; - margin-top: 3rem; - transition: 0.3s ease-in-out; - transition-property: top, padding-top, padding, height; - overflow-y: auto; - } - .col-menu { - border-left: 1px solid var(--color-accent); - } - .col-menu--hide { - top: 1rem; - } - .col-menu .tsd-navigation:not(:last-child) { - padding-bottom: 1.75rem; - } -} - -.tsd-panel { - margin-bottom: 2.5rem; -} -.tsd-panel.tsd-member { - margin-bottom: 4rem; -} -.tsd-panel:empty { - display: none; -} -.tsd-panel > h1, -.tsd-panel > h2, -.tsd-panel > h3 { - margin: 1.5rem -1.5rem 0.75rem -1.5rem; - padding: 0 1.5rem 0.75rem 1.5rem; -} -.tsd-panel > h1.tsd-before-signature, -.tsd-panel > h2.tsd-before-signature, -.tsd-panel > h3.tsd-before-signature { - margin-bottom: 0; - border-bottom: none; -} - -.tsd-panel-group { - margin: 4rem 0; -} -.tsd-panel-group.tsd-index-group { - margin: 2rem 0; -} -.tsd-panel-group.tsd-index-group details { - margin: 2rem 0; -} - -#tsd-search { - transition: background-color 0.2s; -} -#tsd-search .title { - position: relative; - z-index: 2; -} -#tsd-search .field { - position: absolute; - left: 0; - top: 0; - right: 2.5rem; - height: 100%; -} -#tsd-search .field input { - box-sizing: border-box; - position: relative; - top: -50px; - z-index: 1; - width: 100%; - padding: 0 10px; - opacity: 0; - outline: 0; - border: 0; - background: transparent; - color: var(--color-text); -} -#tsd-search .field label { - position: absolute; - overflow: hidden; - right: -40px; -} -#tsd-search .field input, -#tsd-search .title, -#tsd-toolbar-links a { - transition: opacity 0.2s; -} -#tsd-search .results { - position: absolute; - visibility: hidden; - top: 40px; - width: 100%; - margin: 0; - padding: 0; - list-style: none; - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); -} -#tsd-search .results li { - padding: 0 10px; - background-color: var(--color-background); -} -#tsd-search .results li:nth-child(even) { - background-color: var(--color-background-secondary); -} -#tsd-search .results li.state { - display: none; -} -#tsd-search .results li.current, -#tsd-search .results li:hover { - background-color: var(--color-accent); -} -#tsd-search .results a { - display: block; -} -#tsd-search .results a:before { - top: 10px; -} -#tsd-search .results span.parent { - color: var(--color-text-aside); - font-weight: normal; -} -#tsd-search.has-focus { - background-color: var(--color-accent); -} -#tsd-search.has-focus .field input { - top: 0; - opacity: 1; -} -#tsd-search.has-focus .title, -#tsd-search.has-focus #tsd-toolbar-links a { - z-index: 0; - opacity: 0; -} -#tsd-search.has-focus .results { - visibility: visible; -} -#tsd-search.loading .results li.state.loading { - display: block; -} -#tsd-search.failure .results li.state.failure { - display: block; -} - -#tsd-toolbar-links { - position: absolute; - top: 0; - right: 2rem; - height: 100%; - display: flex; - align-items: center; - justify-content: flex-end; -} -#tsd-toolbar-links a { - margin-left: 1.5rem; -} -#tsd-toolbar-links a:hover { - text-decoration: underline; -} - -.tsd-signature { - margin: 0 0 1rem 0; - padding: 1rem 0.5rem; - border: 1px solid var(--color-accent); - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - font-size: 14px; - overflow-x: auto; -} - -.tsd-signature-symbol { - color: var(--color-text-aside); - font-weight: normal; -} - -.tsd-signature-type { - font-style: italic; - font-weight: normal; -} - -.tsd-signatures { - padding: 0; - margin: 0 0 1em 0; - list-style-type: none; -} -.tsd-signatures .tsd-signature { - margin: 0; - border-color: var(--color-accent); - border-width: 1px 0; - transition: background-color 0.1s; -} -.tsd-description .tsd-signatures .tsd-signature { - border-width: 1px; -} - -ul.tsd-parameter-list, -ul.tsd-type-parameter-list { - list-style: square; - margin: 0; - padding-left: 20px; -} -ul.tsd-parameter-list > li.tsd-parameter-signature, -ul.tsd-type-parameter-list > li.tsd-parameter-signature { - list-style: none; - margin-left: -20px; -} -ul.tsd-parameter-list h5, -ul.tsd-type-parameter-list h5 { - font-size: 16px; - margin: 1em 0 0.5em 0; -} -.tsd-sources { - margin-top: 1rem; - font-size: 0.875em; -} -.tsd-sources a { - color: var(--color-text-aside); - text-decoration: underline; -} -.tsd-sources ul { - list-style: none; - padding: 0; -} - -.tsd-page-toolbar { - position: fixed; - z-index: 1; - top: 0; - left: 0; - width: 100%; - color: var(--color-text); - background: var(--color-background-secondary); - border-bottom: 1px var(--color-accent) solid; - transition: transform 0.3s ease-in-out; -} -.tsd-page-toolbar a { - color: var(--color-text); - text-decoration: none; -} -.tsd-page-toolbar a.title { - font-weight: bold; -} -.tsd-page-toolbar a.title:hover { - text-decoration: underline; -} -.tsd-page-toolbar .tsd-toolbar-contents { - display: flex; - justify-content: space-between; - height: 2.5rem; - margin: 0 auto; -} -.tsd-page-toolbar .table-cell { - position: relative; - white-space: nowrap; - line-height: 40px; -} -.tsd-page-toolbar .table-cell:first-child { - width: 100%; -} -.tsd-page-toolbar .tsd-toolbar-icon { - box-sizing: border-box; - line-height: 0; - padding: 12px 0; -} - -.tsd-page-toolbar--hide { - transform: translateY(-100%); -} - -.tsd-widget { - display: inline-block; - overflow: hidden; - opacity: 0.8; - height: 40px; - transition: opacity 0.1s, background-color 0.2s; - vertical-align: bottom; - cursor: pointer; -} -.tsd-widget:hover { - opacity: 0.9; -} -.tsd-widget.active { - opacity: 1; - background-color: var(--color-accent); -} -.tsd-widget.no-caption { - width: 40px; -} -.tsd-widget.no-caption:before { - margin: 0; -} - -.tsd-widget.options, -.tsd-widget.menu { - display: none; -} -@media (max-width: 1024px) { - .tsd-widget.options, - .tsd-widget.menu { - display: inline-block; - } -} -input[type="checkbox"] + .tsd-widget:before { - background-position: -120px 0; -} -input[type="checkbox"]:checked + .tsd-widget:before { - background-position: -160px 0; -} - -img { - max-width: 100%; -} - -.tsd-anchor-icon { - display: inline-flex; - align-items: center; - margin-left: 0.5rem; - vertical-align: middle; - color: var(--color-text); -} - -.tsd-anchor-icon svg { - width: 1em; - height: 1em; - visibility: hidden; -} - -.tsd-anchor-link:hover > .tsd-anchor-icon svg { - visibility: visible; -} - -.deprecated { - text-decoration: line-through; -} - -.warning { - padding: 1rem; - color: var(--color-warning-text); - background: var(--color-background-warning); -} - -* { - scrollbar-width: thin; - scrollbar-color: var(--color-accent) var(--color-icon-background); -} - -*::-webkit-scrollbar { - width: 0.75rem; -} - -*::-webkit-scrollbar-track { - background: var(--color-icon-background); -} - -*::-webkit-scrollbar-thumb { - background-color: var(--color-accent); - border-radius: 999rem; - border: 0.25rem solid var(--color-icon-background); -} diff --git a/docs/classes/AggregateFunctionBuilder.html b/docs/classes/AggregateFunctionBuilder.html deleted file mode 100644 index bee639718..000000000 --- a/docs/classes/AggregateFunctionBuilder.html +++ /dev/null @@ -1,482 +0,0 @@ -AggregateFunctionBuilder | kysely
-
- -
-
-
-
- -

Class AggregateFunctionBuilder<DB, TB, O>

-
-

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 sql template tag implement it.

-
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.

-
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    O = unknown

-
-

Hierarchy

-
    -
  • AggregateFunctionBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
    - -
  • -

    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:

    -
    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):

    -
    select count("id") as "person_count"
    from "person" -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      A extends string

    -
    -

    Parameters

    -
      -
    • -
      alias: A
    -

    Returns AliasedAggregateFunctionBuilder<DB, TB, O, A>

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Adds an over clause (window functions) after the function.

    - - -

    Examples

    -
    -
    const result = await db
    .selectFrom('person')
    .select(
    eb => eb.fn.avg<number>('age').over().as('average_age')
    )
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    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.

    -
    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):

    -
    select avg("age") over(partition by "last_name" order by "first_name" asc) as "average_age"
    from "person" -
    -
    -
    -

    Parameters

    -
    -

    Returns AggregateFunctionBuilder<DB, TB, O>

-
- -
    - -
  • -

    Creates the OperationNode that describes how to compile this expression into SQL.

    -

    If you are creating a custom expression, it's often easiest to use the sql -template tag to build the node:

    -
    class SomeExpression<T> implements Expression<T> {
    toOperationNode(): OperationNode {
    return sql`some sql here`.toOperationNode()
    }
    } -
    -
    -

    Returns AggregateFunctionNode

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/AliasedAggregateFunctionBuilder.html b/docs/classes/AliasedAggregateFunctionBuilder.html deleted file mode 100644 index ba0825f83..000000000 --- a/docs/classes/AliasedAggregateFunctionBuilder.html +++ /dev/null @@ -1,124 +0,0 @@ -AliasedAggregateFunctionBuilder | kysely
-
- -
-
-
-
- -

Class AliasedAggregateFunctionBuilder<DB, TB, O, A>

-
-

AggregateFunctionBuilder with an alias. The result of calling as.

-
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    O = unknown

  • -
  • -

    A extends string = never

-
-

Hierarchy

-
    -
  • AliasedAggregateFunctionBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/AliasedExpressionWrapper.html b/docs/classes/AliasedExpressionWrapper.html deleted file mode 100644 index 68b50248e..000000000 --- a/docs/classes/AliasedExpressionWrapper.html +++ /dev/null @@ -1,123 +0,0 @@ -AliasedExpressionWrapper | kysely
-
- -
-
-
-
- -

Class AliasedExpressionWrapper<T, A>

-
-

Just like Expression<T> but also holds an alias type A.

-

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.

- -

Example

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))
}
} -
-
-
-

Type Parameters

-
    -
  • -

    T

  • -
  • -

    A extends string

-
-

Hierarchy

-
    -
  • AliasedExpressionWrapper
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/AliasedRawBuilder.html b/docs/classes/AliasedRawBuilder.html deleted file mode 100644 index ad4785a57..000000000 --- a/docs/classes/AliasedRawBuilder.html +++ /dev/null @@ -1,116 +0,0 @@ -AliasedRawBuilder | kysely
-
- -
-
-
-
- -

Class AliasedRawBuilder<O, A>

-
-

RawBuilder with an alias. The result of calling as.

-
-
-

Type Parameters

-
    -
  • -

    O = unknown

  • -
  • -

    A extends string = never

-
-

Hierarchy

-
    -
  • AliasedRawBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/AliasedSelectQueryBuilder.html b/docs/classes/AliasedSelectQueryBuilder.html deleted file mode 100644 index 558bc3002..000000000 --- a/docs/classes/AliasedSelectQueryBuilder.html +++ /dev/null @@ -1,124 +0,0 @@ -AliasedSelectQueryBuilder | kysely
-
- -
-
-
-
- -

Class AliasedSelectQueryBuilder<DB, TB, O, A>

-
-

SelectQueryBuilder with an alias. The result of calling as.

-
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    O = undefined

  • -
  • -

    A extends string = never

-
-

Hierarchy

-
    -
  • AliasedSelectQueryBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/AlterColumnBuilder.html b/docs/classes/AlterColumnBuilder.html deleted file mode 100644 index 54ace159c..000000000 --- a/docs/classes/AlterColumnBuilder.html +++ /dev/null @@ -1,188 +0,0 @@ -AlterColumnBuilder | kysely
-
- -
-
-
-
- -

Class AlterColumnBuilder

-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
-
-

Properties

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Properties

-
- -
alterColumnNode: AlterColumnNode
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/AlterTableBuilder.html b/docs/classes/AlterTableBuilder.html deleted file mode 100644 index e0abf8aef..000000000 --- a/docs/classes/AlterTableBuilder.html +++ /dev/null @@ -1,362 +0,0 @@ -AlterTableBuilder | kysely
-
- -
-
-
-
- -

Class AlterTableBuilder

-
-

This builder can be used to create a alter table query.

-
-
-

Hierarchy

-
    -
  • AlterTableBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
    - -
  • -

    See addForeignKeyConstraint

    -

    Unlike addForeignKeyConstraint this method returns -the constraint builder and doesn't take a callback as the last argument. This -is because you can only add one column per ALTER TABLE query.

    -
    -
    -

    Parameters

    -
      -
    • -
      constraintName: string
    • -
    • -
      columns: string[]
    • -
    • -
      targetTable: string
    • -
    • -
      targetColumns: string[]
    -

    Returns AlterTableAddForeignKeyConstraintBuilder

-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -
    -

    Parameters

    -
      -
    • -
      constraintName: string
    -

    Returns AlterTableDropConstraintBuilder

-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/AlterTableColumnAlteringBuilder.html b/docs/classes/AlterTableColumnAlteringBuilder.html deleted file mode 100644 index 0347df468..000000000 --- a/docs/classes/AlterTableColumnAlteringBuilder.html +++ /dev/null @@ -1,216 +0,0 @@ -AlterTableColumnAlteringBuilder | kysely
-
- -
-
-
-
- -

Class AlterTableColumnAlteringBuilder

-
-

Hierarchy

-
    -
  • AlterTableColumnAlteringBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/AlteredColumnBuilder.html b/docs/classes/AlteredColumnBuilder.html deleted file mode 100644 index 442621265..000000000 --- a/docs/classes/AlteredColumnBuilder.html +++ /dev/null @@ -1,218 +0,0 @@ -AlteredColumnBuilder | kysely
-
- -
-
-
-
- -

Class AlteredColumnBuilder

-
-

Allows us to force consumers to do something, anything, when altering a column.

-

Basically, deny the following:

-
db.schema.alterTable('person').alterColumn('age', (ac) => ac)
-
-

Which would now throw a compilation error, instead of a runtime error.

-
-
-

Hierarchy

-
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Properties

-
- -
alterColumnNode: AlterColumnNode
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/CamelCasePlugin.html b/docs/classes/CamelCasePlugin.html deleted file mode 100644 index 0489b11df..000000000 --- a/docs/classes/CamelCasePlugin.html +++ /dev/null @@ -1,209 +0,0 @@ -CamelCasePlugin | kysely
-
- -
-
-
-
- -

Class CamelCasePlugin

-
-

A plugin that converts snake_case identifiers in the database into -camelCase in the javascript side.

-

For example let's assume we have a table called person_table -with columns first_name and last_name in the database. When -using CamelCasePlugin we would setup Kysely like this:

-
interface Person {
firstName: string
lastName: string
}

interface Database {
personTable: Person
}

const db = new Kysely<Database>({
dialect: new PostgresDialect({
database: 'kysely_test',
host: 'localhost',
}),
plugins: [
new CamelCasePlugin()
]
})

const person = await db.selectFrom('personTable')
.where('firstName', '=', 'Arnold')
.select(['firstName', 'lastName'])
.executeTakeFirst()

// generated sql:
// select first_name, last_name from person_table where first_name = $1

if (person) {
console.log(person.firstName)
} -
-

As you can see from the example, everything needs to be defined -in camelCase in the typescript code: the table names, the columns, -schemas, everything. When using the CamelCasePlugin Kysely -works as if the database was defined in camelCase.

-

There are various options you can give to the plugin to modify -the way identifiers are converted. See CamelCasePluginOptions. -If those options are not enough, you can override this plugin's -snakeCase and camelCase methods to make the conversion exactly -the way you like:

-
class MyCamelCasePlugin extends CamelCasePlugin {
protected override snakeCase(str: string): string {
return mySnakeCase(str)
}

protected override camelCase(str: string): string {
return myCamelCase(str)
}
} -
-
-
-

Hierarchy

-
    -
  • CamelCasePlugin
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Properties

-
opt -
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Properties

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
    - -
  • -

    This is called for each query before it is executed. You can modify the query by -transforming its OperationNode tree provided in args.node -and returning the transformed tree. You'd usually want to use an OperationNodeTransformer -for this.

    -

    If you need to pass some query-related data between this method and transformResult you -can use a WeakMap with args.queryId as the key:

    -
    const plugin = {
    data: new WeakMap<QueryId, SomeData>(),

    transformQuery(args: PluginTransformQueryArgs): RootOperationNode {
    this.data.set(args.queryId, something)
    return args.node
    },

    transformResult(args: PluginTransformResultArgs): QueryResult<UnknownRow> {
    const data = this.data.get(args.queryId)
    return args.result
    }
    } -
    -

    You should use a WeakMap instead of a Map or some other strong references because transformQuery -is not always matched by a call to transformResult which would leave orphaned items in the map -and cause a memory leak.

    -
    -
    -

    Parameters

    -
    -

    Returns RootOperationNode

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/CaseBuilder.html b/docs/classes/CaseBuilder.html deleted file mode 100644 index 7492e0200..000000000 --- a/docs/classes/CaseBuilder.html +++ /dev/null @@ -1,153 +0,0 @@ -CaseBuilder | kysely
-
- -
-
-
-
- -

Class CaseBuilder<DB, TB, W, O>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    W = unknown

  • -
  • -

    O = never

-
-

Hierarchy

-
    -
  • CaseBuilder
-
-

Implements

-
    -
  • Whenable<DB, TB, W, O>
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
    - -
  • -
    -

    Type Parameters

    -
      -
    • -

      DB

    • -
    • -

      TB extends string | number | symbol

    • -
    • -

      W = unknown

    • -
    • -

      O = never

    -
    -

    Parameters

    -
      -
    • -
      props: CaseBuilderProps
    -

    Returns CaseBuilder<DB, TB, W, O>

-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/CaseEndBuilder.html b/docs/classes/CaseEndBuilder.html deleted file mode 100644 index 7bc630c03..000000000 --- a/docs/classes/CaseEndBuilder.html +++ /dev/null @@ -1,116 +0,0 @@ -CaseEndBuilder | kysely
-
- -
-
-
-
- -

Class CaseEndBuilder<O>

-
-

Type Parameters

-
    -
  • -

    O

-
-

Hierarchy

-
    -
  • CaseEndBuilder
-
-

Implements

-
    -
  • Endable<O>
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/CaseThenBuilder.html b/docs/classes/CaseThenBuilder.html deleted file mode 100644 index dd534da6f..000000000 --- a/docs/classes/CaseThenBuilder.html +++ /dev/null @@ -1,141 +0,0 @@ -CaseThenBuilder | kysely
-
- -
-
-
-
- -

Class CaseThenBuilder<DB, TB, W, O>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    W

  • -
  • -

    O

-
-

Hierarchy

-
    -
  • CaseThenBuilder
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/CaseWhenBuilder.html b/docs/classes/CaseWhenBuilder.html deleted file mode 100644 index d059b16aa..000000000 --- a/docs/classes/CaseWhenBuilder.html +++ /dev/null @@ -1,214 +0,0 @@ -CaseWhenBuilder | kysely
-
- -
-
-
-
- -

Class CaseWhenBuilder<DB, TB, W, O>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    W

  • -
  • -

    O

-
-

Hierarchy

-
    -
  • CaseWhenBuilder
-
-

Implements

-
    -
  • Whenable<DB, TB, W, O>
  • -
  • Endable<O | null>
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/ColumnDefinitionBuilder.html b/docs/classes/ColumnDefinitionBuilder.html deleted file mode 100644 index 251795899..000000000 --- a/docs/classes/ColumnDefinitionBuilder.html +++ /dev/null @@ -1,438 +0,0 @@ -ColumnDefinitionBuilder | kysely
-
- -
-
-
-
- -

Class ColumnDefinitionBuilder

-
-

Hierarchy

-
    -
  • ColumnDefinitionBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Adds a default value constraint for the column.

    - - -

    Examples

    -
    -
    db.schema
    .createTable('pet')
    .addColumn('number_of_legs', 'integer', (col) => col.defaultTo(4))
    .execute() -
    -

    Values passed to defaultTo are interpreted as value literals by default. You can define -an arbitrary SQL expression using the sql template tag:

    -
    importsql } from 'kysely'

    db.schema
    .createTable('pet')
    .addColumn(
    'number_of_legs',
    'integer',
    (col) => col.defaultTo(sql`any SQL here`)
    )
    .execute() -
    -
    -
    -

    Parameters

    -
      -
    • -
      value: unknown
    -

    Returns ColumnDefinitionBuilder

-
- -
-
- -
-
- -
-
- -
    - -
  • -

    This can be used to add any additional SQL to the end of the column definition.

    - - -

    Examples

    -
    -
    db.schema.createTable('person')
    .addColumn('id', 'integer', col => col.primaryKey())
    .addColumn('age', 'integer', col => col.unsigned().notNull().modifyEnd(sql`comment ${sql.lit('it is not polite to ask a woman her age')}`))
    .execute() -
    -

    The generated SQL (MySQL):

    -
    create table `person` (
    `id` integer primary key,
    `age` integer unsigned not null comment 'it is not polite to ask a woman her age'
    ) -
    -
    -
    -

    Parameters

    -
    -

    Returns ColumnDefinitionBuilder

-
- -
    - -
  • -

    This can be used to add any additional SQL right after the column's data type.

    - - -

    Examples

    -
    -
    db.schema.createTable('person')
    .addColumn('id', 'integer', col => col.primaryKey())
    .addColumn('first_name', 'varchar(36)', col => col.modifyFront(sql`collate utf8mb4_general_ci`).notNull())
    .execute() -
    -

    The generated SQL (MySQL):

    -
    create table `person` (
    `id` integer primary key,
    `first_name` varchar(36) collate utf8mb4_general_ci not null
    ) -
    -
    -
    -

    Parameters

    -
    -

    Returns ColumnDefinitionBuilder

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/ConnectionBuilder.html b/docs/classes/ConnectionBuilder.html deleted file mode 100644 index 2ac4bf757..000000000 --- a/docs/classes/ConnectionBuilder.html +++ /dev/null @@ -1,121 +0,0 @@ -ConnectionBuilder | kysely
-
- -
-
-
-
- -

Class ConnectionBuilder<DB>

-
-

Type Parameters

-
    -
  • -

    DB

-
-

Hierarchy

-
    -
  • ConnectionBuilder
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -
    -

    Type Parameters

    -
      -
    • -

      T

    -
    -

    Parameters

    -
      -
    • -
      callback: ((db: Kysely<DB>) => Promise<T>)
      -
        -
      • -
          -
        • (db: Kysely<DB>): Promise<T>
        • -
        • -
          -

          Parameters

          -
          -

          Returns Promise<T>

    -

    Returns Promise<T>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/CreateIndexBuilder.html b/docs/classes/CreateIndexBuilder.html deleted file mode 100644 index 0dfe55dd1..000000000 --- a/docs/classes/CreateIndexBuilder.html +++ /dev/null @@ -1,389 +0,0 @@ -CreateIndexBuilder | kysely
-
- -
-
-
-
- -

Class CreateIndexBuilder<C>

-
-

Type Parameters

-
    -
  • -

    C = never

-
-

Hierarchy

-
    -
  • CreateIndexBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
    - -
  • -

    Adds a column to the index.

    -

    Also see columns for adding multiple columns at once or expression -for specifying an arbitrary expression.

    - - -

    Examples

    -
    -
    await db.schema
    .createIndex('person_first_name_and_age_index')
    .on('person')
    .column('first_name')
    .column('age desc')
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    create index "person_first_name_and_age_index" on "person" ("first_name", "age" desc)
    -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      CL extends string

    -
    -

    Parameters

    -
      -
    • -
      column: OrderedColumnName<CL>
    -

    Returns CreateIndexBuilder<C | ExtractColumnNameFromOrderedColumnName<CL>>

-
- -
    - -
  • -

    Specifies a list of columns for the index.

    -

    Also see column for adding a single column or expression for -specifying an arbitrary expression.

    - - -

    Examples

    -
    -
    await db.schema
    .createIndex('person_first_name_and_age_index')
    .on('person')
    .columns(['first_name', 'age desc'])
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    create index "person_first_name_and_age_index" on "person" ("first_name", "age" desc)
    -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      CL extends string

    -
    -

    Parameters

    -
      -
    • -
      columns: OrderedColumnName<CL>[]
    -

    Returns CreateIndexBuilder<C | ExtractColumnNameFromOrderedColumnName<CL>>

-
- -
-
- -
-
- -
    - -
  • -

    Specifies an arbitrary expression for the index.

    - - -

    Examples

    -
    -
    importsql } from 'kysely'

    await db.schema
    .createIndex('person_first_name_index')
    .on('person')
    .expression(sql`first_name COLLATE "fi_FI"`)
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    create index "person_first_name_index" on "person" (first_name COLLATE "fi_FI")
    -
    -
    -
    -

    Parameters

    -
    -

    Returns CreateIndexBuilder<C>

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/CreateSchemaBuilder.html b/docs/classes/CreateSchemaBuilder.html deleted file mode 100644 index 6bdf7bc20..000000000 --- a/docs/classes/CreateSchemaBuilder.html +++ /dev/null @@ -1,161 +0,0 @@ -CreateSchemaBuilder | kysely
-
- -
-
-
-
- -

Class CreateSchemaBuilder

-
-

Hierarchy

-
    -
  • CreateSchemaBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/CreateTableBuilder.html b/docs/classes/CreateTableBuilder.html deleted file mode 100644 index aa9cd5775..000000000 --- a/docs/classes/CreateTableBuilder.html +++ /dev/null @@ -1,469 +0,0 @@ -CreateTableBuilder | kysely
-
- -
-
-
-
- -

Class CreateTableBuilder<TB, C>

-
-

This builder can be used to create a create table query.

-
-
-

Type Parameters

-
    -
  • -

    TB extends string

  • -
  • -

    C extends string = never

-
-

Hierarchy

-
    -
  • CreateTableBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    Calls the given function passing this as the only argument.

    - - -

    Examples

    -
    -
    db.schema
    .createTable('test')
    .$call((builder) => builder.addColumn('id', 'integer'))
    .execute() -
    -
    const addDefaultColumns = <T extends string, C extends string = never>(
    builder: CreateTableBuilder<T, C>
    ) => {
    return builder
    .addColumn('id', 'integer', (col) => col.notNull())
    .addColumn('created_at', 'date', (col) =>
    col.notNull().defaultTo(sql`now()`)
    )
    .addColumn('updated_at', 'date', (col) =>
    col.notNull().defaultTo(sql`now()`)
    )
    }

    db.schema
    .createTable('test')
    .$call(addDefaultColumns)
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -
    -

    Parameters

    -
    -

    Returns T

-
- -
-
- -
    - -
  • -

    Adds a column to the table.

    - - -

    Examples

    -
    -
    importsql } from 'kysely'

    await db.schema
    .createTable('person')
    .addColumn('id', 'integer', (col) => col.autoIncrement().primaryKey()),
    .addColumn('first_name', 'varchar(50)', (col) => col.notNull())
    .addColumn('last_name', 'varchar(255)')
    .addColumn('bank_balance', 'numeric(8, 2)')
    // You can specify any data type using the `sql` tag if the types
    // don't include it.
    .addColumn('data', sql`any_type_here`)
    .addColumn('parent_id', 'integer', (col) =>
    col.references('person.id').onDelete('cascade'))
    ) -
    -

    With this method, it's once again good to remember that Kysely just builds the -query and doesn't provide the same API for all databses. For example, some -databases like older MySQL don't support the references statement in the -column definition. Instead foreign key constraints need to be defined in the -create table query. See the next example:

    -
      .addColumn('parent_id', 'integer')
    .addForeignKeyConstraint(
    'person_parent_id_fk', ['parent_id'], 'person', ['id'],
    (cb) => cb.onDelete('cascade')
    ) -
    -

    Another good example is that PostgreSQL doesn't support the auto_increment -keyword and you need to define an autoincrementing column for example using -serial:

    -
    await db.schema
    .createTable('person')
    .addColumn('id', 'serial', (col) => col.primaryKey()), -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      CN extends string

    -
    -

    Parameters

    -
    -

    Returns CreateTableBuilder<TB, C | CN>

-
- -
    - -
  • -

    Adds a foreign key constraint.

    -

    The constraint name can be anything you want, but it must be unique -across the whole database.

    - - -

    Examples

    -
    -
    addForeignKeyConstraint(
    'owner_id_foreign',
    ['owner_id'],
    'person',
    ['id'],
    ) -
    -

    Add constraint for multiple columns:

    -
    addForeignKeyConstraint(
    'owner_id_foreign',
    ['owner_id1', 'owner_id2'],
    'person',
    ['id1', 'id2'],
    (cb) => cb.onDelete('cascade')
    ) -
    -
    -
    -

    Parameters

    -
    -

    Returns CreateTableBuilder<TB, C>

-
- -
    - -
  • -

    Adds a primary key constraint for one or more columns.

    -

    The constraint name can be anything you want, but it must be unique -across the whole database.

    - - -

    Examples

    -
    -
    addPrimaryKeyConstraint('primary_key', ['first_name', 'last_name'])
    -
    -
    -
    -

    Parameters

    -
      -
    • -
      constraintName: string
    • -
    • -
      columns: C[]
    -

    Returns CreateTableBuilder<TB, C>

-
- -
    - -
  • -

    Adds a unique constraint for one or more columns.

    -

    The constraint name can be anything you want, but it must be unique -across the whole database.

    - - -

    Examples

    -
    -
    addUniqueConstraint('first_name_last_name_unique', ['first_name', 'last_name'])
    -
    -
    -
    -

    Parameters

    -
      -
    • -
      constraintName: string
    • -
    • -
      columns: C[]
    -

    Returns CreateTableBuilder<TB, C>

-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    This can be used to add any additional SQL to the end of the query.

    -

    Also see onCommit.

    - - -

    Examples

    -
    -
    db.schema.createTable('person')
    .addColumn('id', 'integer', col => col => primaryKey())
    .addColumn('first_name', 'varchar(64)', col => col.notNull())
    .addColumn('last_name', 'varchar(64), col => col.notNull())
    .modifyEnd(sql`collate utf8_unicode_ci`)
    .execute() -
    -

    The generated SQL (MySQL):

    -
    create table `person` (
    `id` integer primary key,
    `first_name` varchar(64) not null,
    `last_name` varchar(64) not null
    ) collate utf8_unicode_ci -
    -
    -
    -

    Parameters

    -
    -

    Returns CreateTableBuilder<TB, C>

-
- -
    - -
  • -

    This can be used to add any additional SQL to the front of the query after the create keyword.

    -

    Also see temporary.

    - - -

    Examples

    -
    -
    db.schema.createTable('person')
    .modifyFront(sql`global temporary`)
    .addColumn('id', 'integer', col => col.primaryKey())
    .addColumn('first_name', 'varchar(64)', col => col.notNull())
    .addColumn('last_name', 'varchar(64), col => col.notNull())
    .execute() -
    -

    The generated SQL (Postgres):

    -
    create global temporary table "person" (
    "id" integer primary key,
    "first_name" varchar(64) not null,
    "last_name" varchar(64) not null
    ) -
    -
    -
    -

    Parameters

    -
    -

    Returns CreateTableBuilder<TB, C>

-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/CreateTypeBuilder.html b/docs/classes/CreateTypeBuilder.html deleted file mode 100644 index d0c211373..000000000 --- a/docs/classes/CreateTypeBuilder.html +++ /dev/null @@ -1,174 +0,0 @@ -CreateTypeBuilder | kysely
-
- -
-
-
-
- -

Class CreateTypeBuilder

-
-

Hierarchy

-
    -
  • CreateTypeBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/CreateViewBuilder.html b/docs/classes/CreateViewBuilder.html deleted file mode 100644 index 8887a1bbc..000000000 --- a/docs/classes/CreateViewBuilder.html +++ /dev/null @@ -1,233 +0,0 @@ -CreateViewBuilder | kysely
-
- -
-
-
-
- -

Class CreateViewBuilder

-
-

Hierarchy

-
    -
  • CreateViewBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DeduplicateJoinsPlugin.html b/docs/classes/DeduplicateJoinsPlugin.html deleted file mode 100644 index 9c661e098..000000000 --- a/docs/classes/DeduplicateJoinsPlugin.html +++ /dev/null @@ -1,129 +0,0 @@ -DeduplicateJoinsPlugin | kysely
-
- -
-
-
-
- -

Class DeduplicateJoinsPlugin

-
-

Plugin that removes duplicate joins from queries.

-

See this recipe

-
-
-

Hierarchy

-
    -
  • DeduplicateJoinsPlugin
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    This is called for each query before it is executed. You can modify the query by -transforming its OperationNode tree provided in args.node -and returning the transformed tree. You'd usually want to use an OperationNodeTransformer -for this.

    -

    If you need to pass some query-related data between this method and transformResult you -can use a WeakMap with args.queryId as the key:

    -
    const plugin = {
    data: new WeakMap<QueryId, SomeData>(),

    transformQuery(args: PluginTransformQueryArgs): RootOperationNode {
    this.data.set(args.queryId, something)
    return args.node
    },

    transformResult(args: PluginTransformResultArgs): QueryResult<UnknownRow> {
    const data = this.data.get(args.queryId)
    return args.result
    }
    } -
    -

    You should use a WeakMap instead of a Map or some other strong references because transformQuery -is not always matched by a call to transformResult which would leave orphaned items in the map -and cause a memory leak.

    -
    -
    -

    Parameters

    -
    -

    Returns RootOperationNode

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DefaultConnectionProvider.html b/docs/classes/DefaultConnectionProvider.html deleted file mode 100644 index ffee6a8ea..000000000 --- a/docs/classes/DefaultConnectionProvider.html +++ /dev/null @@ -1,119 +0,0 @@ -DefaultConnectionProvider | kysely
-
- -
-
-
-
- -

Class DefaultConnectionProvider

-
-

Hierarchy

-
    -
  • DefaultConnectionProvider
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DefaultQueryCompiler.html b/docs/classes/DefaultQueryCompiler.html deleted file mode 100644 index 19115d247..000000000 --- a/docs/classes/DefaultQueryCompiler.html +++ /dev/null @@ -1,1681 +0,0 @@ -DefaultQueryCompiler | kysely
-
- -
-
-
-
- -

Class DefaultQueryCompiler

-
-

a QueryCompiler compiles a query expressed as a tree of OperationNodes into SQL.

-
-
-

Hierarchy

-
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Properties

-
-
-

Accessors

-
-
-

Methods

-
addParameter -append -appendImmediateValue -appendValue -compileDistinctOn -compileList -compileQuery -compileUnwrappedIdentifier -getAutoIncrement -getCurrentParameterPlaceholder -getExplainOptionAssignment -getExplainOptionsDelimiter -getLeftExplainOptionsWrapper -getLeftIdentifierWrapper -getRightExplainOptionsWrapper -getRightIdentifierWrapper -getSql -isMinusOperator -sanitizeIdentifier -visitAddColumn -visitAddConstraint -visitAggregateFunction -visitAlias -visitAlterColumn -visitAlterTable -visitAnd -visitBinaryOperation -visitCase -visitCheckConstraint -visitColumn -visitColumnDefinition -visitColumnUpdate -visitCommonTableExpression -visitCommonTableExpressionName -visitCreateIndex -visitCreateSchema -visitCreateTable -visitCreateType -visitCreateView -visitDataType -visitDefaultInsertValue -visitDefaultValue -visitDeleteQuery -visitDropColumn -visitDropConstraint -visitDropIndex -visitDropSchema -visitDropTable -visitDropType -visitDropView -visitExplain -visitForeignKeyConstraint -visitFrom -visitFunction -visitGenerated -visitGroupBy -visitGroupByItem -visitHaving -visitIdentifier -visitInsertQuery -visitJoin -visitLimit -visitList -visitModifyColumn -visitNode -visitOffset -visitOn -visitOnConflict -visitOnDuplicateKey -visitOperator -visitOr -visitOrderBy -visitOrderByItem -visitOver -visitParens -visitPartitionBy -visitPartitionByItem -visitPrimaryKeyConstraint -visitPrimitiveValueList -visitRaw -visitReference -visitReferences -visitRenameColumn -visitReturning -visitSchemableIdentifier -visitSelectAll -visitSelectModifier -visitSelectQuery -visitSelection -visitSetOperation -visitTable -visitUnaryOperation -visitUniqueConstraint -visitUpdateQuery -visitUsing -visitValue -visitValueList -visitValues -visitWhen -visitWhere -visitWith -
-
-

Constructors

-
- -
-
-

Properties

-
- -
nodeStack: OperationNode[] = []
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DefaultQueryExecutor.html b/docs/classes/DefaultQueryExecutor.html deleted file mode 100644 index 83a9b4dbe..000000000 --- a/docs/classes/DefaultQueryExecutor.html +++ /dev/null @@ -1,310 +0,0 @@ -DefaultQueryExecutor | kysely
-
- -
-
-
-
- -

Class DefaultQueryExecutor

-
-

Hierarchy

-
    -
  • QueryExecutorBase -
      -
    • DefaultQueryExecutor
-
-
-
- -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DeleteQueryBuilder.html b/docs/classes/DeleteQueryBuilder.html deleted file mode 100644 index ad9659dd0..000000000 --- a/docs/classes/DeleteQueryBuilder.html +++ /dev/null @@ -1,1345 +0,0 @@ -DeleteQueryBuilder | kysely
-
- -
-
-
-
- -

Class DeleteQueryBuilder<DB, TB, O>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    O

-
-

Hierarchy

-
    -
  • DeleteQueryBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    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

    -
    -
    const result = await db
    .with('deleted_person', (qb) => qb
    .deleteFrom('person')
    .where('id', '=', person.id)
    .returning('first_name')
    .$assertType<{ first_name: string }>()
    )
    .with('deleted_pet', (qb) => qb
    .deleteFrom('pet')
    .where('owner_id', '=', person.id)
    .returning(['name as pet_name', 'species'])
    .$assertType<{ pet_name: string, species: Species }>()
    )
    .selectFrom(['deleted_person', 'deleted_pet'])
    .selectAll()
    .executeTakeFirstOrThrow() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -

    Returns O extends T ? DeleteQueryBuilder<DB, TB, T> : KyselyTypeError<"$assertType() call failed: The type passed in is not equal to the output type of the query.">

-
- -
    - -
  • -

    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 $if method.

    - - -

    Examples

    -
    -

    The next example uses a helper function log to log a query:

    -
    function log<T extends Compilable>(qb: T): T {
    console.log(qb.compile())
    return qb
    }

    db.deleteFrom('person')
    .$call(log)
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -
    -

    Parameters

    -
    -

    Returns T

-
- -
-
- -
    - -
  • -

    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

    -
    -
    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:

    -
    {
    id: number
    first_name: string
    last_name?: string
    } -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      O2

    -
    -

    Parameters

    -
    -

    Returns O2 extends DeleteResult ? DeleteQueryBuilder<DB, TB, DeleteResult> : O2 extends O & E ? DeleteQueryBuilder<DB, TB, O & Partial<E>> : DeleteQueryBuilder<DB, TB, Partial<O2>>

-
- -
    - -
  • -

    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 where and returning or 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:

    -
    const person = await db.deleteFrom('person')
    .where('id', '=', id)
    .where('nullable_column', 'is not', null)
    .returningAll()
    .executeTakeFirstOrThrow()

    if (person.nullable_column) {
    functionThatExpectsPersonWithNonNullValue(person)
    } -
    -

    Into this:

    -
    const person = await db.deleteFrom('person')
    .where('id', '=', id)
    .where('nullable_column', 'is not', null)
    .returningAll()
    .$narrowType<{ nullable_column: string }>()
    .executeTakeFirstOrThrow()

    functionThatExpectsPersonWithNonNullValue(person) -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -

    Returns DeleteQueryBuilder<DB, TB, NarrowPartial<O, T>>

-
- -
    - -
  • -
    -

    Deprecated

    Use $assertType instead.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -

    Returns O extends T ? DeleteQueryBuilder<DB, TB, T> : KyselyTypeError<"assertType() call failed: The type passed in is not equal to the output type of the query.">

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Executes the query and returns the first result or undefined if -the query returned no result.

    -
    -

    Returns Promise<SimplifySingleResult<O>>

-
- -
    - -
  • -

    Executes the query and returns the first result or throws if -the query returned no result.

    -

    By default an instance of NoResultError is thrown, but you can -provide a custom error class, or callback as the only argument to throw a different -error.

    -
    -
    -

    Parameters

    -
    -

    Returns Promise<SimplifyResult<O>>

-
- -
    - -
  • -

    Executes query with explain statement before the main query.

    -
    const explained = await db
    .selectFrom('person')
    .where('gender', '=', 'female')
    .selectAll()
    .explain('json') -
    -

    The generated SQL (MySQL):

    -
    explain format=json select * from `person` where `gender` = ?
    -
    -

    You can also execute explain analyze statements.

    -
    import { sql } from 'kysely'

    const explained = await db
    .selectFrom('person')
    .where('gender', '=', 'female')
    .selectAll()
    .explain('json', sql`analyze`) -
    -

    The generated SQL (PostgreSQL):

    -
    explain (analyze, format json) select * from "person" where "gender" = $1
    -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      ER extends Record<string, any> = Record<string, any>

    -
    -

    Parameters

    -
    -

    Returns Promise<ER[]>

-
- -
-
- -
-
- -
    - -
  • -

    Joins another table to the query using an inner join.

    - - -

    Examples

    -
    -

    Simple usage by providing a table name and two columns to join:

    -
    const result = await db
    .selectFrom('person')
    .innerJoin('pet', 'pet.owner_id', 'person.id')
    // `select` needs to come after the call to `innerJoin` so
    // that you can select from the joined table.
    .select('person.id', 'pet.name')
    .execute()

    result[0].id
    result[0].name -
    -

    The generated SQL (PostgreSQL):

    -
    select "person"."id", "pet"."name"
    from "person"
    inner join "pet"
    on "pet"."owner_id" = "person"."id" -
    -

    You can give an alias for the joined table like this:

    -
    await db.selectFrom('person')
    .innerJoin('pet as p', 'p.owner_id', 'person.id')
    .where('p.name', '=', 'Doggo')
    .selectAll()
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select *
    from "person"
    inner join "pet" as "p"
    on "p"."owner_id" = "person"."id"
    where "p".name" = $1 -
    -

    You can provide a function as the second argument to get a join -builder for creating more complex joins. The join builder has a -bunch of on* methods for building the on clause of the join. -There's basically an equivalent for every where method -(on, onRef, onExists etc.). You can do all the same things -with the on method that you can with the corresponding where -method. See the where method documentation for more examples.

    -
    await db.selectFrom('person')
    .innerJoin(
    'pet',
    (join) => join
    .onRef('pet.owner_id', '=', 'person.id')
    .on('pet.name', '=', 'Doggo')
    )
    .selectAll()
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select *
    from "person"
    inner join "pet"
    on "pet"."owner_id" = "person"."id"
    and "pet"."name" = $1 -
    -

    You can join a subquery by providing a select query (or a callback) -as the first argument:

    -
    await db.selectFrom('person')
    .innerJoin(
    qb.selectFrom('pet')
    .select(['owner_id', 'name'])
    .where('name', '=', 'Doggo')
    .as('doggos'),
    'doggos.owner_id',
    'person.id',
    )
    .selectAll()
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select *
    from "person"
    inner join (
    select "owner_id", "name"
    from "pet"
    where "name" = $1
    ) as "doggos"
    on "doggos"."owner_id" = "person"."id" -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, TB>

    • -
    • -

      K1 extends string

    • -
    • -

      K2 extends string

    -
    -

    Parameters

    -
      -
    • -
      table: TE
    • -
    • -
      k1: K1
    • -
    • -
      k2: K2
    -

    Returns DeleteQueryBuilderWithInnerJoin<DB, TB, O, TE>

  • - -
  • -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      table: TE
    • -
    • -
      callback: FN
    -

    Returns DeleteQueryBuilderWithInnerJoin<DB, TB, O, TE>

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Allows you to return data from modified rows.

    -

    On supported databases like PostgreSQL, this method can be chained to -insert, update and delete queries to return data.

    -

    Note that on SQLite you need to give aliases for the expressions to avoid -this bug in SQLite. -For example .returning('id as id').

    -

    Also see the returningAll method.

    - - -

    Examples

    -
    -

    Return one column:

    -
    const { id } = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .returning('id')
    .executeTakeFirst() -
    -

    Return multiple columns:

    -
    const { id, first_name } = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .returning(['id', 'last_name'])
    .executeTakeFirst() -
    -

    Return arbitrary expressions:

    -
    importsql } 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('pets').select('pet.id').limit(1).as('first_pet_id')
    ])
    .executeTakeFirst() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      SE extends string | AliasedExpression<any, any> | DynamicReferenceBuilder<any> | AliasedExpressionFactory<DB, TB>

    -
    -

    Parameters

    -
    -

    Returns DeleteQueryBuilder<DB, TB, ReturningRow<DB, TB, O, SE>>

-
- -
    - -
  • -

    Adds returning * or returning table.* clause to the query.

    - - -

    Examples

    -
    -

    Return all columns.

    -
    const pets = await db
    .deleteFrom('pet')
    .returningAll()
    .execute() -
    -

    The generated SQL (PostgreSQL)

    -
    delete from "pet" returning *
    -
    -

    Return all columns from all tables

    -
    const result = ctx.db
    .deleteFrom('toy')
    .using(['pet', 'person'])
    .whereRef('toy.pet_id', '=', 'pet.id')
    .whereRef('pet.owner_id', '=', 'person.id')
    .where('person.first_name', '=', 'Zoro')
    .returningAll()
    .execute() -
    -

    The generated SQL (PostgreSQL)

    -
    delete from "toy"
    using "pet", "person"
    where "toy"."pet_id" = "pet"."id"
    and "pet"."owner_id" = "person"."id"
    and "person"."first_name" = $1
    returning * -
    -

    Return all columns from a single table.

    -
    const result = ctx.db
    .deleteFrom('toy')
    .using(['pet', 'person'])
    .whereRef('toy.pet_id', '=', 'pet.id')
    .whereRef('pet.owner_id', '=', 'person.id')
    .where('person.first_name', '=', 'Itachi')
    .returningAll('pet')
    .execute() -
    -

    The generated SQL (PostgreSQL)

    -
    delete from "toy"
    using "pet", "person"
    where "toy"."pet_id" = "pet"."id"
    and "pet"."owner_id" = "person"."id"
    and "person"."first_name" = $1
    returning "pet".* -
    -

    Return all columns from multiple tables.

    -
    const result = ctx.db
    .deleteFrom('toy')
    .using(['pet', 'person'])
    .whereRef('toy.pet_id', '=', 'pet.id')
    .whereRef('pet.owner_id', '=', 'person.id')
    .where('person.first_name', '=', 'Luffy')
    .returningAll(['toy', 'pet'])
    .execute() -
    -

    The generated SQL (PostgreSQL)

    -
    delete from "toy"
    using "pet", "person"
    where "toy"."pet_id" = "pet"."id"
    and "pet"."owner_id" = "person"."id"
    and "person"."first_name" = $1
    returning "toy".*, "pet".* -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T extends string | number | symbol

    -
    -

    Parameters

    -
      -
    • -
      tables: readonly T[]
    -

    Returns DeleteQueryBuilder<DB, TB, ReturningAllRow<DB, T, O>>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      T extends string | number | symbol

    -
    -

    Parameters

    -
      -
    • -
      table: T
    -

    Returns DeleteQueryBuilder<DB, TB, ReturningAllRow<DB, T, O>>

  • - -
  • -

    Returns DeleteQueryBuilder<DB, TB, ReturningAllRow<DB, TB, O>>

-
- -
-
- -
    - -
  • -

    Executes the query and streams the rows.

    -

    The optional argument chunkSize defines how many rows to fetch from the database -at a time. It only affects some dialects like PostgreSQL that support it.

    - - -

    Examples

    -
    -
    const stream = db.
    .selectFrom('person')
    .select(['first_name', 'last_name'])
    .where('gender', '=', 'other')
    .stream()

    for await (const person of stream) {
    console.log(person.first_name)

    if (person.last_name === 'Something') {
    // Breaking or returning before the stream has ended will release
    // the database connection and invalidate the stream.
    break
    }
    } -
    -
    -
    -

    Parameters

    -
      -
    • -
      chunkSize: number = 100
    -

    Returns AsyncIterableIterator<O>

-
- -
-
- -
    - -
  • -

    Adds a using clause to the query.

    -

    This clause allows adding additional tables to the query for filtering/returning -only. Usually a non-standard syntactic-sugar alternative to a where with a sub-query.

    - - -

    Examples:

    -
    -
    await db
    .deleteFrom('pet')
    .using('person')
    .whereRef('pet.owner_id', '=', 'person.id')
    .where('person.first_name', '=', 'Bob')
    .executeTakeFirstOrThrow() -
    -

    The generated SQL (PostgreSQL):

    -
    delete from "pet"
    using "person"
    where "pet"."owner_id" = "person"."id"
    and "person"."first_name" = $1 -
    -

    On supported databases such as MySQL, this clause allows using joins, but requires -at least one of the tables after the from keyword to be also named after -the using keyword. See also innerJoin, leftJoin, rightJoin -and fullJoin.

    -
    await db
    .deleteFrom('pet')
    .using('pet')
    .leftJoin('person', 'person.id', 'pet.owner_id')
    .where('person.first_name', '=', 'Bob')
    .executeTakeFirstOrThrow() -
    -

    The generated SQL (MySQL):

    -
    delete from `pet`
    using `pet`
    left join `person` on `person`.`id` = `pet`.`owner_id`
    where `person`.`first_name` = ? -
    -

    You can also chain multiple invocations of this method, or pass an array to -a single invocation to name multiple tables.

    -
    await db
    .deleteFrom('toy')
    .using(['pet', 'person'])
    .whereRef('toy.pet_id', '=', 'pet.id')
    .whereRef('pet.owner_id', '=', 'person.id')
    .where('person.first_name', '=', 'Bob')
    .returning('pet.name')
    .executeTakeFirstOrThrow() -
    -

    The generated SQL (PostgreSQL):

    -
    delete from "toy"
    using "pet", "person"
    where "toy"."pet_id" = "pet"."id"
    and "pet"."owner_id" = "person"."id"
    and "person"."first_name" = $1
    returning "pet"."name" -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, keyof DB>

    -
    -

    Parameters

    -
      -
    • -
      tables: TE[]
    -

    Returns DeleteQueryBuilder<From<DB, TE>, FromTables<DB, TB, TE>, O>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, keyof DB>

    -
    -

    Parameters

    -
      -
    • -
      table: TE
    -

    Returns DeleteQueryBuilder<From<DB, TE>, FromTables<DB, TB, TE>, O>

-
- -
    - -
  • -

    Adds a where expression to the query.

    -

    Calling this method multiple times will combine the expressions using and.

    -

    Also see whereRef

    - - -

    Examples

    -
    -
    const person = await db
    .selectFrom('person')
    .selectAll()
    .where('first_name', '=', 'Jennifer')
    .where('age', '>', 40)
    .executeTakeFirst() -
    -

    The generated SQL (PostgreSQL):

    -
    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:

    -
    sql`your operator`
    -
    -

    You can add expressions conditionally like this:

    -
    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)
    }

    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 ExpressionBuilder passed to the callback:

    -
    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):

    -
    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:

    -
    const persons = await db
    .selectFrom('person')
    .selectAll()
    .where('person.id', 'in', [100, 200, 300])
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "person" where "id" in ($1, $2, $3)
    -
    -

    For complex where expressions you can pass in a single callback and -use the ExpressionBuilder to build your expression:

    -
    const persons = await db
    .selectFrom('person')
    .selectAll('person')
    .where(({ cmpr, or, and, not, exists, selectFrom, val }) => and([
    or([
    cmpr('first_name', '=', firstName),
    cmpr('age', '<', maxAge)
    ]),
    not(exists(
    selectFrom('pet').select('pet.id').whereRef('pet.owner_id', '=', 'person.id')
    ))
    ])) -
    -

    The generated SQL (PostgreSQL):

    -
    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 sql tag -as any of the arguments, including the operator:

    -
    importsql } from 'kysely'

    const persons = await db
    .selectFrom('person')
    .selectAll()
    .where(
    sql`coalesce(first_name, last_name)`,
    'like',
    '%' + name + '%',
    )
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    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 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 sql tag or db.dynamic. The example below -uses both:

    -
    importsql } from 'kysely'
    const { ref } = db.dynamic

    const persons = await db
    .selectFrom('person')
    .selectAll()
    .where(ref(columnFromUserInput), '=', 1)
    .where(sql.id(columnFromUserInput), '=', 2)
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      RE extends string | Expression<any> | DynamicReferenceBuilder<any> | SelectQueryBuilder<any, any, {}> | SelectQueryBuilderFactory<DB, TB, {}> | ExpressionFactory<DB, TB, any>

    -
    -

    Parameters

    -
    -

    Returns DeleteQueryBuilder<DB, TB, O>

  • - -
  • -
    -

    Parameters

    -
    -

    Returns DeleteQueryBuilder<DB, TB, O>

  • - -
  • -
    -

    Parameters

    -
    -

    Returns DeleteQueryBuilder<DB, TB, O>

-
- -
-
- -
-
- -
    - -
  • -

    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:

    -
    db.selectFrom(['person', 'pet'])
    .selectAll()
    .whereRef('person.first_name', '=', 'pet.name') -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "person", "pet" where "person"."first_name" = "pet"."name"
    -
    -

    Usage in a subquery:

    -
    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"

    -
    -
    -

    Parameters

    -
    -

    Returns DeleteQueryBuilder<DB, TB, O>

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DeleteResult.html b/docs/classes/DeleteResult.html deleted file mode 100644 index 58c573972..000000000 --- a/docs/classes/DeleteResult.html +++ /dev/null @@ -1,90 +0,0 @@ -DeleteResult | kysely
-
- -
-
-
-
- -

Class DeleteResult

-
-

Hierarchy

-
    -
  • DeleteResult
-
-
-
- -
-
-

Constructors

-
-
-

Accessors

-
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DialectAdapterBase.html b/docs/classes/DialectAdapterBase.html deleted file mode 100644 index 059333a0d..000000000 --- a/docs/classes/DialectAdapterBase.html +++ /dev/null @@ -1,182 +0,0 @@ -DialectAdapterBase | kysely
-
- -
-
-
-
- -

Class DialectAdapterBaseAbstract

-
-

A basic implementation of DialectAdapter with sensible default values. -3rd party dialects can extend this instead of implementing the DialectAdapter -interface from scratch. That way all new settings will get default values when -they are added and there will be less breaking changes.

-
-
-

Hierarchy

-
-
-

Implements

-
-
-

Implemented by

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
    - -
  • -

    This method is used to acquire a lock for the migrations so that -it's not possible for two migration operations to run in parallel.

    -

    Most dialects have explicit locks that can be used, like advisory locks -in PostgreSQL and the get_lock function in MySQL.

    -

    If the dialect doesn't have explicit locks the lockTable -created by Kysely can be used instead. You can access it through the options object. -The lock table has two columns id and is_locked and there's only one row in the table -whose id is lockRowId. is_locked is an integer. Kysely -takes care of creating the lock table and inserting the one single row to it before this -method is executed. If the dialect supports schemas and the user has specified a custom -schema in their migration settings, the options object also contains the schema name in -lockTableSchema.

    -

    Here's an example of how you might implement this method for a dialect that doesn't -have explicit locks but supports FOR UPDATE row locks and transactional DDL:

    -
    {
    async acquireMigrationLock(db, options): Promise<void> {
    const queryDb = options.lockTableSchema
    ? db.withSchema(options.lockTableSchema)
    : db

    // Since our imaginary dialect supports transactional DDL and has
    // row locks, we can simply take a row lock here and it will guarantee
    // all subsequent calls to this method from other transactions will
    // wait until this transaction finishes.
    await queryDb
    .selectFrom(options.lockTable)
    .selectAll()
    .where('id', '=', options.lockRowId)
    .forUpdate()
    .execute()
    }
    } -
    -

    If supportsTransactionalDdl is true then the db passed to this method -is a transaction inside which the migrations will be executed. Otherwise -db is a single connection (session) that will be used to execute the -migrations.

    -
    -
    -

    Parameters

    -
    -

    Returns Promise<void>

-
- -
    - -
  • -

    Releases the migration lock. See acquireMigrationLock.

    -

    If supportsTransactionalDdl is true then the db passed to this method -is a transaction inside which the migrations were executed. Otherwise db -is a single connection (session) that was used to execute the migrations -and the acquireMigrationLock call.

    -
    -
    -

    Parameters

    -
    -

    Returns Promise<void>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DropIndexBuilder.html b/docs/classes/DropIndexBuilder.html deleted file mode 100644 index 1a83983e5..000000000 --- a/docs/classes/DropIndexBuilder.html +++ /dev/null @@ -1,189 +0,0 @@ -DropIndexBuilder | kysely
-
- -
-
-
-
- -

Class DropIndexBuilder

-
-

Hierarchy

-
    -
  • DropIndexBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DropSchemaBuilder.html b/docs/classes/DropSchemaBuilder.html deleted file mode 100644 index 0ba352ac2..000000000 --- a/docs/classes/DropSchemaBuilder.html +++ /dev/null @@ -1,171 +0,0 @@ -DropSchemaBuilder | kysely
-
- -
-
-
-
- -

Class DropSchemaBuilder

-
-

Hierarchy

-
    -
  • DropSchemaBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DropTableBuilder.html b/docs/classes/DropTableBuilder.html deleted file mode 100644 index d8b3392ae..000000000 --- a/docs/classes/DropTableBuilder.html +++ /dev/null @@ -1,171 +0,0 @@ -DropTableBuilder | kysely
-
- -
-
-
-
- -

Class DropTableBuilder

-
-

Hierarchy

-
    -
  • DropTableBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DropTypeBuilder.html b/docs/classes/DropTypeBuilder.html deleted file mode 100644 index db60d1b68..000000000 --- a/docs/classes/DropTypeBuilder.html +++ /dev/null @@ -1,161 +0,0 @@ -DropTypeBuilder | kysely
-
- -
-
-
-
- -

Class DropTypeBuilder

-
-

Hierarchy

-
    -
  • DropTypeBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DropViewBuilder.html b/docs/classes/DropViewBuilder.html deleted file mode 100644 index c30907dd1..000000000 --- a/docs/classes/DropViewBuilder.html +++ /dev/null @@ -1,181 +0,0 @@ -DropViewBuilder | kysely
-
- -
-
-
-
- -

Class DropViewBuilder

-
-

Hierarchy

-
    -
  • DropViewBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DummyDriver.html b/docs/classes/DummyDriver.html deleted file mode 100644 index 30087491e..000000000 --- a/docs/classes/DummyDriver.html +++ /dev/null @@ -1,185 +0,0 @@ -DummyDriver | kysely
-
- -
-
-
-
- -

Class DummyDriver

-
-

A driver that does absolutely nothing.

-

You can use this to create Kysely instances solely for building queries

- - -

Examples

-
-

This example creates a Kysely instance for building postgres queries:

-
const db = new Kysely<Database>({
dialect: {
createAdapter() {
return new PostgresAdapter()
},
createDriver() {
return new DummyDriver()
},
createIntrospector(db: Kysely<any>) {
return new PostgresIntrospector(db)
},
createQueryCompiler() {
return new PostgresQueryCompiler()
},
},
}) -
-

You can use it to build a query and compile it to SQL but trying to -execute the query will throw an error.

-
const { sql } = db.selectFrom('person').selectAll().compile()
console.log(sql) // select * from "person" -
-
-
-

Hierarchy

-
    -
  • DummyDriver
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Initializes the driver.

    -

    After calling this method the driver should be usable and acquireConnection etc. -methods should be callable.

    -
    -

    Returns Promise<void>

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/DynamicModule.html b/docs/classes/DynamicModule.html deleted file mode 100644 index a35f45925..000000000 --- a/docs/classes/DynamicModule.html +++ /dev/null @@ -1,121 +0,0 @@ -DynamicModule | kysely
-
- -
-
-
-
- -

Class DynamicModule

-
-

Hierarchy

-
    -
  • DynamicModule
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
ref -
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    Creates a dynamic reference to a column that is not know at compile time.

    -

    Kysely is built in a way that by default you can't refer to tables or columns -that are not actually visible in the current query and context. This is all -done by typescript at compile time, which means that you need to know the -columns and tables at compile time. This is not always the case of course.

    -

    This method is meant to be used in those cases where the column names -come from the user input or are not otherwise known at compile time.

    -

    WARNING! Unlike values, column names are not escaped by the database engine -or Kysely and if you pass in unchecked column names using this method, you -create an SQL injection vulnerability. Always always validate the user -input before passing it to this method.

    -

    There are couple of examples below for some use cases, but you can pass -ref to other methods as well. If the types allow you to pass a ref -value to some place, it should work.

    - - -

    Examples

    -
    -

    Filter by a column not know at compile time:

    -
    async function someQuery(filterColumn: string, filterValue: string) {
    const { ref } = db.dynamic

    return await db
    .selectFrom('person')
    .selectAll()
    .where(ref(filterColumn), '=', filterValue)
    .execute()
    }

    someQuery('first_name', 'Arnold')
    someQuery('person.last_name', 'Aniston') -
    -

    Order by a column not know at compile time:

    -
    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') -
    -

    In this example we add selections dynamically:

    -
    const { ref } = db.dynamic

    // Some column name provided by the user. Value not known at compile time.
    const columnFromUserInput = req.query.select;

    // A type that lists all possible values `columnFromUserInput` can have.
    // You can use `keyof Person` if any column of an interface is allowed.
    type PossibleColumns = 'last_name' | 'first_name' | 'birth_date'

    const [person] = await db.selectFrom('person')
    .select([
    ref<PossibleColumns>(columnFromUserInput),
    'id'
    ])
    .execute()

    // The resulting type contains all `PossibleColumns` as optional fields
    // because we cannot know which field was actually selected before
    // running the code.
    const lastName: string | undefined = person.last_name
    const firstName: string | undefined = person.first_name
    const birthDate: string | undefined = person.birth_date

    // The result type also contains the compile time selection `id`.
    person.id -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      R extends string = never

    -
    -

    Parameters

    -
      -
    • -
      reference: string
    -

    Returns DynamicReferenceBuilder<R>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/ExpressionWrapper.html b/docs/classes/ExpressionWrapper.html deleted file mode 100644 index 65b6e12f3..000000000 --- a/docs/classes/ExpressionWrapper.html +++ /dev/null @@ -1,182 +0,0 @@ -ExpressionWrapper | kysely
-
- -
-
-
-
- -

Class ExpressionWrapper<T>

-
-

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 sql template tag implement it.

-
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.

-
-
-

Type Parameters

-
    -
  • -

    T

-
-

Hierarchy

-
    -
  • ExpressionWrapper
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
    - -
  • -

    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:

    -
    const result = await db
    .selectFrom('person')
    .select(eb =>
    eb.cmpr('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):

    -
    select "first_name" = $1 as "is_jennifer"
    from "person" -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      A extends string

    -
    -

    Parameters

    -
      -
    • -
      alias: A
    -

    Returns AliasedExpression<T, A>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      A extends string

    -
    -

    Parameters

    -
    -

    Returns AliasedExpression<T, A>

-
- -
    - -
  • -

    Creates the OperationNode that describes how to compile this expression into SQL.

    -

    If you are creating a custom expression, it's often easiest to use the sql -template tag to build the node:

    -
    class SomeExpression<T> implements Expression<T> {
    toOperationNode(): OperationNode {
    return sql`some sql here`.toOperationNode()
    }
    } -
    -
    -

    Returns OperationNode

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/FileMigrationProvider.html b/docs/classes/FileMigrationProvider.html deleted file mode 100644 index c9dc7a83b..000000000 --- a/docs/classes/FileMigrationProvider.html +++ /dev/null @@ -1,115 +0,0 @@ -FileMigrationProvider | kysely
-
- -
-
-
-
- -

Class FileMigrationProvider

-
-

Reads all migrations from a folder in node.js.

- - -

Examples

-
-
import { promises as fs } from 'fs'
import path from 'path'

new FileMigrationProvider({
fs,
path,
migrationFolder: 'path/to/migrations/folder'
}) -
-
-
-

Hierarchy

-
    -
  • FileMigrationProvider
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    Returns all migrations, old and new.

    -

    For example if you have your migrations in a folder as separate files, -you can implement this method to return all migration in that folder -as Migration objects.

    -

    Kysely already has a built-in FileMigrationProvider for node.js -that does exactly that.

    -

    The keys of the returned object are migration names and values are the -migrations. The order of the migrations is determined by the alphabetical -order of the migration names. The items in the object don't need to be -sorted, they are sorted by Kysely.

    -
    -

    Returns Promise<Record<string, Migration>>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/ForeignKeyConstraintBuilder.html b/docs/classes/ForeignKeyConstraintBuilder.html deleted file mode 100644 index 70fef3e4f..000000000 --- a/docs/classes/ForeignKeyConstraintBuilder.html +++ /dev/null @@ -1,162 +0,0 @@ -ForeignKeyConstraintBuilder | kysely
-
- -
-
-
-
- -

Class ForeignKeyConstraintBuilder

-
-

Hierarchy

-
    -
  • ForeignKeyConstraintBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/InsertQueryBuilder.html b/docs/classes/InsertQueryBuilder.html deleted file mode 100644 index 52015903c..000000000 --- a/docs/classes/InsertQueryBuilder.html +++ /dev/null @@ -1,850 +0,0 @@ -InsertQueryBuilder | kysely
-
- -
-
-
-
- -

Class InsertQueryBuilder<DB, TB, O>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    O

-
-

Hierarchy

-
    -
  • InsertQueryBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    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

    -
    -
    const result = await db
    .with('new_person', (qb) => qb
    .insertInto('person')
    .values(person)
    .returning('id')
    .$assertType<{ id: string }>()
    )
    .with('new_pet', (qb) => qb
    .insertInto('pet')
    .values((eb) => ({ owner_id: eb.selectFrom('new_person').select('id'), ...pet }))
    .returning(['name as pet_name', 'species'])
    .$assertType<{ pet_name: string, species: Species }>()
    )
    .selectFrom(['new_person', 'new_pet'])
    .selectAll()
    .executeTakeFirstOrThrow() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -

    Returns O extends T ? InsertQueryBuilder<DB, TB, T> : KyselyTypeError<"$assertType() call failed: The type passed in is not equal to the output type of the query.">

-
- -
    - -
  • -

    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 $if method.

    - - -

    Examples

    -
    -

    The next example uses a helper function log to log a query:

    -
    function log<T extends Compilable>(qb: T): T {
    console.log(qb.compile())
    return qb
    }

    db.updateTable('person')
    .set(values)
    .$call(log)
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -
    -

    Parameters

    -
    -

    Returns T

-
- -
-
- -
    - -
  • -

    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

    -
    -
    async function insertPerson(values: InsertablePerson, returnLastName: boolean) {
    return await db
    .insertInto('person')
    .values(values)
    .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 insertPerson function is:

    -
    {
    id: number
    first_name: string
    last_name?: string
    } -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      O2

    -
    -

    Parameters

    -
    -

    Returns O2 extends InsertResult ? InsertQueryBuilder<DB, TB, InsertResult> : O2 extends O & E ? InsertQueryBuilder<DB, TB, O & Partial<E>> : InsertQueryBuilder<DB, TB, Partial<O2>>

-
- -
    - -
  • -

    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 values input -when using returning or 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:

    -
    const person = await db.insertInto('person')
    .values({ ...inputPerson, nullable_column: 'hell yeah!' })
    .returningAll()
    .executeTakeFirstOrThrow()

    if (nullable_column) {
    functionThatExpectsPersonWithNonNullValue(person)
    } -
    -

    Into this:

    -
    const person = await db.insertInto('person')
    .values({ ...inputPerson, nullable_column: 'hell yeah!' })
    .returningAll()
    .$narrowType<{ nullable_column: string }>()
    .executeTakeFirstOrThrow()

    functionThatExpectsPersonWithNonNullValue(person) -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -

    Returns InsertQueryBuilder<DB, TB, NarrowPartial<O, T>>

-
- -
    - -
  • -
    -

    Deprecated

    Use $assertType instead.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -

    Returns O extends T ? InsertQueryBuilder<DB, TB, T> : KyselyTypeError<"assertType() call failed: The type passed in is not equal to the output type of the query.">

-
- -
-
- -
-
- -
    - -
  • -

    Sets the columns to insert.

    -

    The values method sets both the columns and the values and this method -is not needed. But if you are using the expression method, you can use -this method to set the columns to insert.

    - - -

    Examples

    -
    -
    db.insertInto('person')
    .columns(['first_name'])
    .expression((eb) => eb.selectFrom('pet').select('pet.name')) -
    -

    The generated SQL (PostgreSQL):

    -
    insert into "person" ("first_name")
    select "pet"."name" from "pet" -
    -
    -
    -

    Parameters

    -
      -
    • -
      columns: readonly (keyof DB[TB] & string)[]
    -

    Returns InsertQueryBuilder<DB, TB, O>

-
- -
-
- -
-
- -
    - -
  • -

    Executes the query and returns the first result or undefined if -the query returned no result.

    -
    -

    Returns Promise<SimplifySingleResult<O>>

-
- -
    - -
  • -

    Executes the query and returns the first result or throws if -the query returned no result.

    -

    By default an instance of NoResultError is thrown, but you can -provide a custom error class, or callback as the only argument to throw a different -error.

    -
    -
    -

    Parameters

    -
    -

    Returns Promise<SimplifyResult<O>>

-
- -
    - -
  • -

    Executes query with explain statement before the main query.

    -
    const explained = await db
    .selectFrom('person')
    .where('gender', '=', 'female')
    .selectAll()
    .explain('json') -
    -

    The generated SQL (MySQL):

    -
    explain format=json select * from `person` where `gender` = ?
    -
    -

    You can also execute explain analyze statements.

    -
    import { sql } from 'kysely'

    const explained = await db
    .selectFrom('person')
    .where('gender', '=', 'female')
    .selectAll()
    .explain('json', sql`analyze`) -
    -

    The generated SQL (PostgreSQL):

    -
    explain (analyze, format json) select * from "person" where "gender" = $1
    -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      ER extends Record<string, any> = Record<string, any>

    -
    -

    Parameters

    -
    -

    Returns Promise<ER[]>

-
- -
    - -
  • -

    Insert an arbitrary expression. For example the result of a select query.

    - - -

    Examples

    -
    -
    db.insertInto('person')
    .columns(['first_name'])
    .expression((eb) => eb.selectFrom('pet').select('pet.name')) -
    -

    The generated SQL (PostgreSQL):

    -
    insert into "person" ("first_name")
    select "pet"."name" from "pet" -
    -
    -
    -

    Parameters

    -
      -
    • -
      expression: ExpressionOrFactory<DB, TB, any>
    -

    Returns InsertQueryBuilder<DB, TB, O>

-
- -
-
- -
    - -
  • -

    Changes an insert into query to an insert ignore into query.

    -

    If you use the ignore modifier, ignorable errors that occur while executing the -insert statement are ignored. For example, without ignore, a row that duplicates -an existing unique index or primary key value in the table causes a duplicate-key -error and the statement is aborted. With ignore, the row is discarded and no error -occurs.

    -

    This is only supported on some dialects like MySQL. On most dialects you should -use the onConflict method.

    - - -

    Examples

    -
    -
    await db.insertInto('person')
    .ignore()
    .values(values)
    .execute() -
    -
    -

    Returns InsertQueryBuilder<DB, TB, O>

-
- -
    - -
  • -

    Adds an on conflict clause to the query.

    -

    on conflict is only supported by some dialects like PostgreSQL and SQLite. On MySQL -you can use ignore and onDuplicateKeyUpdate to achieve similar results.

    - - -

    Examples

    -
    -
    await db
    .insertInto('pet')
    .values({
    name: 'Catto',
    species: 'cat',
    })
    .onConflict((oc) => oc
    .column('name')
    .doUpdateSet({ species: 'hamster' })
    )
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    insert into "pet" ("name", "species")
    values ($1, $2)
    on conflict ("name")
    do update set "species" = $3 -
    -

    You can provide the name of the constraint instead of a column name:

    -
    await db
    .insertInto('pet')
    .values({
    name: 'Catto',
    species: 'cat',
    })
    .onConflict((oc) => oc
    .constraint('pet_name_key')
    .doUpdateSet({ species: 'hamster' })
    )
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    insert into "pet" ("name", "species")
    values ($1, $2)
    on conflict on constraint "pet_name_key"
    do update set "species" = $3 -
    -

    You can also specify an expression as the conflict target in case -the unique index is an expression index:

    -
    import { sql } from 'kysely'

    await db
    .insertInto('pet')
    .values({
    name: 'Catto',
    species: 'cat',
    })
    .onConflict((oc) => oc
    .expression(sql`lower(name)`)
    .doUpdateSet({ species: 'hamster' })
    )
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    insert into "pet" ("name", "species")
    values ($1, $2)
    on conflict (lower(name))
    do update set "species" = $3 -
    -

    You can add a filter for the update statement like this:

    -
    await db
    .insertInto('pet')
    .values({
    name: 'Catto',
    species: 'cat',
    })
    .onConflict((oc) => oc
    .column('name')
    .doUpdateSet({ species: 'hamster' })
    .where('excluded.name', '!=', 'Catto'')
    )
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    insert into "pet" ("name", "species")
    values ($1, $2)
    on conflict ("name")
    do update set "species" = $3
    where "excluded"."name" != $4 -
    -

    You can create an on conflict do nothing clauses like this:

    -
    await db
    .insertInto('pet')
    .values({
    name: 'Catto',
    species: 'cat',
    })
    .onConflict((oc) => oc
    .column('name')
    .doNothing()
    )
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    insert into "pet" ("name", "species")
    values ($1, $2)
    on conflict ("name") do nothing -
    -

    You can refer to the columns of the virtual excluded table -in a type-safe way using a callback and the ref method of -ExpressionBuilder:

    -
    db.insertInto('person')
    .values(person)
    .onConflict(oc => oc
    .column('id')
    .doUpdateSet({
    first_name: (eb) => eb.ref('excluded.first_name'),
    last_name: (eb) => eb.ref('excluded.last_name')
    })
    ) -
    -
    -
    -

    Parameters

    -
    -

    Returns InsertQueryBuilder<DB, TB, O>

-
- -
    - -
  • -

    Adds on duplicate key update to the query.

    -

    If you specify on duplicate key update, and a row is inserted that would cause -a duplicate value in a unique index or primary key, an update of the old row occurs.

    -

    This is only implemented by some dialects like MySQL. On most dialects you should -use onConflict instead.

    - - -

    Examples

    -
    -
    await db
    .insertInto('person')
    .values(values)
    .onDuplicateKeyUpdate({ species: 'hamster' }) -
    -
    -
    -

    Parameters

    -
      -
    • -
      update: UpdateExpression<DB, TB, TB>
    -

    Returns InsertQueryBuilder<DB, TB, O>

-
- -
    - -
  • -

    Allows you to return data from modified rows.

    -

    On supported databases like PostgreSQL, this method can be chained to -insert, update and delete queries to return data.

    -

    Note that on SQLite you need to give aliases for the expressions to avoid -this bug in SQLite. -For example .returning('id as id').

    -

    Also see the returningAll method.

    - - -

    Examples

    -
    -

    Return one column:

    -
    const { id } = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .returning('id')
    .executeTakeFirst() -
    -

    Return multiple columns:

    -
    const { id, first_name } = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .returning(['id', 'last_name'])
    .executeTakeFirst() -
    -

    Return arbitrary expressions:

    -
    importsql } 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('pets').select('pet.id').limit(1).as('first_pet_id')
    ])
    .executeTakeFirst() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      SE extends string | AliasedExpression<any, any> | DynamicReferenceBuilder<any> | AliasedExpressionFactory<DB, TB>

    -
    -

    Parameters

    -
    -

    Returns InsertQueryBuilder<DB, TB, ReturningRow<DB, TB, O, SE>>

-
- -
-
- -
    - -
  • -

    Executes the query and streams the rows.

    -

    The optional argument chunkSize defines how many rows to fetch from the database -at a time. It only affects some dialects like PostgreSQL that support it.

    - - -

    Examples

    -
    -
    const stream = db.
    .selectFrom('person')
    .select(['first_name', 'last_name'])
    .where('gender', '=', 'other')
    .stream()

    for await (const person of stream) {
    console.log(person.first_name)

    if (person.last_name === 'Something') {
    // Breaking or returning before the stream has ended will release
    // the database connection and invalidate the stream.
    break
    }
    } -
    -
    -
    -

    Parameters

    -
      -
    • -
      chunkSize: number = 100
    -

    Returns AsyncIterableIterator<O>

-
- -
-
- -
    - -
  • -

    Sets the values to insert for an insert query.

    -

    This method takes an object whose keys are column names and values are -values to insert. In addition to the column's type, the values can be -raw sql snippets or select queries.

    -

    You must provide all fields you haven't explicitly marked as nullable -or optional using Generated or ColumnType.

    -

    The return value of an insert query is an instance of InsertResult. The -insertId field holds the auto incremented primary -key if the database returned one.

    -

    On PostgreSQL and some other dialects, you need to call returning to get -something out of the query.

    -

    Also see the expression method for inserting the result of a select -query or any other expression.

    - - -

    Examples

    -
    -

    Insert a row into person:

    -
    const result = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .executeTakeFirstOrThrow() -
    -

    The generated SQL (PostgreSQL):

    -
    insert into "person" ("first_name", "last_name") values ($1, $2)
    -
    -

    On dialects that support it (for example PostgreSQL) you can insert multiple -rows by providing an array. Note that the return value is once again very -dialect-specific. Some databases may only return the id of the last inserted -row and some return nothing at all unless you call returning.

    -
    await db
    .insertInto('person')
    .values([{
    first_name: 'Jennifer',
    last_name: 'Aniston'
    }, {
    first_name: 'Arnold',
    last_name: 'Schwarzenegger',
    }])
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    insert into "person" ("first_name", "last_name") values (($1, $2), ($3, $4))
    -
    -

    On PostgreSQL you need to chain returning to the query to get -the inserted row's columns (or any other expression) as the -return value:

    -
    const row = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .returning('id')
    .executeTakeFirstOrThrow()

    row.id -
    -

    The generated SQL (PostgreSQL):

    -
    insert into "person" ("first_name", "last_name") values ($1, $2) returning "id"
    -
    -

    In addition to primitives, the values can also be raw sql expressions or -select queries:

    -
    import { sql } from 'kysely'

    const result = await db
    .insertInto('person')
    .values((eb) => ({
    first_name: 'Jennifer',
    last_name: sql`${'Ani'} || ${'ston'}`,
    middle_name: eb.ref('first_name'),
    age: eb.selectFrom('person').select(sql`avg(age)`),
    }))
    .executeTakeFirst()

    console.log(result.insertId) -
    -

    The generated SQL (PostgreSQL):

    -
    insert into "person" ("first_name", "last_name", "age")
    values ($1, $2 || $3, (select avg(age) from "person")) -
    -

    You can also use the callback version of subqueries or raw expressions:

    -
    db.with('jennifer', (db) => db
    .selectFrom('person')
    .where('first_name', '=', 'Jennifer')
    .select(['id', 'first_name', 'gender'])
    .limit(1)
    ).insertInto('pet').values((eb) => ({
    owner_id: eb.selectFrom('jennifer').select('id'),
    name: eb.selectFrom('jennifer').select('first_name'),
    species: 'cat',
    })) -
    -
    -
    -

    Parameters

    -
      -
    • -
      insert: InsertObjectOrList<DB, TB>
    -

    Returns InsertQueryBuilder<DB, TB, O>

  • - -
  • -
    -

    Parameters

    -
      -
    • -
      insert: InsertObjectOrListFactory<DB, TB>
    -

    Returns InsertQueryBuilder<DB, TB, O>

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/InsertResult.html b/docs/classes/InsertResult.html deleted file mode 100644 index a82763983..000000000 --- a/docs/classes/InsertResult.html +++ /dev/null @@ -1,122 +0,0 @@ -InsertResult | kysely
-
- -
-
-
-
- -

Class InsertResult

-
-

The result of an insert query.

-

If the table has an auto incrementing primary key insertId will hold -the generated id on dialects that support it. For example PostgreSQL doesn't -return the id by default and insertId is undefined. On PostgreSQL you -need to use returning or returningAll -to get out the inserted id.

-

numInsertedOrUpdatedRows holds the number of (actually) inserted rows. -On MySQL, updated rows are counted twice when using on duplicate key update.

- - -

Examples

-
-
const result = await db
.insertInto('person')
.values(person)
.executeTakeFirst()

console.log(result.insertId) -
-
-
-

Hierarchy

-
    -
  • InsertResult
-
-
-
- -
-
-

Constructors

-
-
-

Accessors

-
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/JoinBuilder.html b/docs/classes/JoinBuilder.html deleted file mode 100644 index b04a7ffc6..000000000 --- a/docs/classes/JoinBuilder.html +++ /dev/null @@ -1,373 +0,0 @@ -JoinBuilder | kysely
-
- -
-
-
-
- -

Class JoinBuilder<DB, TB>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-

Hierarchy

-
    -
  • JoinBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    Simply calls the provided function passing this as the only argument. $call returns -what the provided function returns.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -
    -

    Parameters

    -
    -

    Returns T

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/Kysely.html b/docs/classes/Kysely.html deleted file mode 100644 index 09e48d4e5..000000000 --- a/docs/classes/Kysely.html +++ /dev/null @@ -1,815 +0,0 @@ -Kysely | kysely
-
- -
-
-
-
- -

Class Kysely<DB>

-
-

The main Kysely class.

-

You should create one instance of Kysely per database using the Kysely -constructor. Each Kysely instance maintains it's own connection pool.

- - -

Examples

-
-

This example assumes your database has tables person and pet:

-
importKysely, Generated, PostgresDialect } from 'kysely'

interface PersonTable {
id: Generated<number>
first_name: string
last_name: string
}

interface PetTable {
id: Generated<number>
owner_id: number
name: string
species 'cat' | 'dog'
}

interface Database {
person: PersonTable,
pet: PetTable
}

const db = new Kysely<Database>({
dialect: new PostgresDialect({
host: 'localhost',
database: 'kysely_test',
})
}) -
-
-
-

Type Parameters

-
    -
  • -

    DB

    -

    The database interface type. Keys of this type must be table names - in the database and values must be interfaces that describe the rows in those - tables. See the examples above.

    -
-
-

Hierarchy

-
-
-

Implements

-
    -
  • QueryExecutorProvider
-
-
-
- -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
- -
    -
  • get fn(): FunctionModule<DB, keyof DB>
  • -
  • -

    Returns a FunctionModule that can be used to write type safe function -calls.

    -
    const { count } = db.fn

    await db.selectFrom('person')
    .innerJoin('pet', 'pet.owner_id', 'person.id')
    .select([
    'person.id',
    count('pet.id').as('pet_count')
    ])
    .groupBy('person.id')
    .having(count('pet.id'), '>', 10)
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    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 -
    -
    -

    Returns FunctionModule<DB, keyof DB>

-
- -
-
- -
    -
  • get isTransaction(): boolean
  • -
  • -

    Returns true if this Kysely instance is a transaction.

    -

    You can also use db instanceof Transaction.

    -
    -

    Returns boolean

-
- -
-
-

Methods

-
- -
-
- -
    - -
  • -

    Provides a kysely instance bound to a single database connection.

    - - -

    Examples

    -
    -
    await db
    .connection()
    .execute(async (db) => {
    // `db` is an instance of `Kysely` that's bound to a single
    // database connection. All queries executed through `db` use
    // the same connection.
    await doStuff(db)
    }) -
    -
    -

    Returns ConnectionBuilder<DB>

-
- -
    - -
  • -

    Creates a delete query.

    -

    See the where method for examples on how to specify -a where clause for the delete operation.

    -

    The return value of the query is an instance of DeleteResult.

    - - -

    Examples

    -
    -

    Deleting person with id 1:

    -
    const result = await db
    .deleteFrom('person')
    .where('person.id', '=', 1)
    .executeTakeFirst()

    console.log(result.numDeletedRows) -
    -

    The generated SQL (PostgreSQL):

    -
    delete from "person" where "person"."id" = $1
    -
    -

    Some databases such as MySQL support deleting from multiple tables:

    -
    const result = await db
    .deleteFrom(['person', 'pet'])
    .using('person')
    .innerJoin('pet', 'pet.owner_id', '=', 'person.id')
    .where('person.id', '=', 1)
    .executeTakeFirst() -
    -

    The generated SQL (MySQL):

    -
    delete from `person`, `pet`
    using `person`
    inner join `pet` on `pet`.`owner_id` = `person`.`id`
    where `person`.`id` = ? -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TR extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TR[]
    -

    Returns DeleteQueryBuilder<DB, ExtractTableAlias<DB, TR>, DeleteResult>

  • - -
  • -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      tables: TR[]
    -

    Returns DeleteQueryBuilder<DrainOuterGeneric<{ [ C in any]: C extends ExtractAliasFromTableExpression<DB, TR> ? ExtractRowTypeFromTableExpression<DB, TR, C> : C extends keyof DB ? DB[C] : never }>, DrainOuterGeneric<ExtractAliasFromTableExpression<DB, TR>>, DeleteResult>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TR extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TR
    -

    Returns DeleteQueryBuilder<DB, ExtractTableAlias<DB, TR>, DeleteResult>

  • - -
  • -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      table: TR
    -

    Returns DeleteQueryBuilder<DrainOuterGeneric<{ [ C in any]: C extends ExtractAliasFromTableExpression<DB, TR> ? ExtractRowTypeFromTableExpression<DB, TR, C> : C extends keyof DB ? DB[C] : never }>, DrainOuterGeneric<ExtractAliasFromTableExpression<DB, TR>>, DeleteResult>

-
- -
    - -
  • -

    Releases all resources and disconnects from the database.

    -

    You need to call this when you are done using the Kysely instance.

    -
    -

    Returns Promise<void>

-
- -
-
- -
    - -
  • -

    Creates an insert query.

    -

    The return value of this query is an instance of InsertResult. InsertResult -has the insertId field that holds the auto incremented id of -the inserted row if the db returned one.

    -

    See the values method for more info and examples. Also see -the returning method for a way to return columns -on supported databases like PostgreSQL.

    - - -

    Examples

    -
    -
    const result = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .executeTakeFirst()

    console.log(result.insertId) -
    -

    Some databases like PostgreSQL support the returning method:

    -
    const { id } = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .returning('id')
    .executeTakeFirst() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T extends string

    -
    -

    Parameters

    -
      -
    • -
      table: T
    -

    Returns InsertQueryBuilder<DB, T, InsertResult>

-
- -
-
- -
    - -
  • -

    Creates a select query builder for the given table or tables.

    -

    The tables passed to this method are built as the query's from clause.

    - - -

    Examples

    -
    -

    Create a select query for one table:

    -
    db.selectFrom('person').selectAll()
    -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "person"
    -
    -

    Create a select query for one table with an alias:

    -
    const persons = await db.selectFrom('person as p')
    .select(['p.id', 'first_name'])
    .execute()

    console.log(persons[0].id) -
    -

    The generated SQL (PostgreSQL):

    -
    select "p"."id", "first_name" from "person" as "p"
    -
    -

    Create a select query from a subquery:

    -
    const persons = await db.selectFrom(
    (eb) => eb.selectFrom('person').select('person.id as identifier').as('p')
    )
    .select('p.identifier')
    .execute()

    console.log(persons[0].identifier) -
    -

    The generated SQL (PostgreSQL):

    -
    select "p"."identifier",
    from (
    select "person"."id" as "identifier" from "person"
    ) as p -
    -

    Create a select query from raw sql:

    -
    importsql } from 'kysely'

    const items = await db
    .selectFrom(sql<{ one: number }>`(select 1 as one)`.as('q'))
    .select('q.one')
    .execute()

    console.log(items[0].one) -
    -

    The generated SQL (PostgreSQL):

    -
    select "q"."one",
    from (
    select 1 as one
    ) as q -
    -

    When you use the sql tag you need to also provide the result type of the -raw snippet / query so that Kysely can figure out what columns are -available for the rest of the query.

    -

    The selectFrom method also accepts an array for multiple tables. All -the above examples can also be used in an array.

    -
    importsql } from 'kysely'

    const items = await db.selectFrom([
    'person as p',
    db.selectFrom('pet').select('pet.species').as('a'),
    sql<{ one: number }>`(select 1 as one)`.as('q')
    ])
    .select(['p.id', 'a.species', 'q.one'])
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select "p".id, "a"."species", "q"."one"
    from
    "person" as "p",
    (select "pet"."species" from "pet") as a,
    (select 1 as one) as "q" -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TE extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TE[]
    -

    Returns SelectQueryBuilder<DB, ExtractTableAlias<DB, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, keyof DB>

    -
    -

    Parameters

    -
      -
    • -
      from: TE[]
    -

    Returns SelectQueryBuilder<DrainOuterGeneric<{ [ C in any]: C extends ExtractAliasFromTableExpression<DB, TE> ? ExtractRowTypeFromTableExpression<DB, TE, C> : C extends keyof DB ? DB[C] : never }>, DrainOuterGeneric<ExtractAliasFromTableExpression<DB, TE>>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TE
    -

    Returns SelectQueryBuilder<DB, ExtractTableAlias<DB, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends `${string} as ${string}`

    -
    -

    Parameters

    -
      -
    • -
      from: TE
    -

    Returns SelectQueryBuilder<DB & PickTableWithAlias<DB, TE>, ExtractTableAlias<DB, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, keyof DB>

    -
    -

    Parameters

    -
      -
    • -
      from: TE
    -

    Returns SelectQueryBuilder<DrainOuterGeneric<{ [ C in any]: C extends ExtractAliasFromTableExpression<DB, TE> ? ExtractRowTypeFromTableExpression<DB, TE, C> : C extends keyof DB ? DB[C] : never }>, DrainOuterGeneric<ExtractAliasFromTableExpression<DB, TE>>, {}>

-
- -
    - -
  • -

    Creates a TransactionBuilder that can be used to run queries inside a transaction.

    -

    The returned TransactionBuilder can be used to configure the transaction. The -execute method can then be called to run the transaction. -execute takes a function that is run inside the -transaction. If the function throws, the transaction is rolled back. Otherwise -the transaction is committed.

    -

    The callback function passed to the execute -method gets the transaction object as its only argument. The transaction is -of type Transaction which inherits Kysely. Any query -started through the transaction object is executed inside the transaction.

    - - -

    Examples

    -
    -
    const catto = await db.transaction().execute(async (trx) => {
    const jennifer = await trx.insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston',
    })
    .returning('id')
    .executeTakeFirstOrThrow()

    await someFunction(trx, jennifer)

    return await trx.insertInto('pet')
    .values({
    user_id: jennifer.id,
    name: 'Catto',
    species: 'cat'
    })
    .returningAll()
    .executeTakeFirst()
    }) -
    -

    Setting the isolation level:

    -
    await db
    .transaction()
    .setIsolationLevel('serializable')
    .execute(async (trx) => {
    await doStuff(trx)
    }) -
    -
    -

    Returns TransactionBuilder<DB>

-
- -
    - -
  • -

    Creates an update query.

    -

    See the where method for examples on how to specify -a where clause for the update operation.

    -

    See the set method for examples on how to -specify the updates.

    -

    The return value of the query is an UpdateResult.

    - - -

    Examples

    -
    -
    const result = await db
    .updateTable('person')
    .set({ first_name: 'Jennifer' })
    .where('person.id', '=', 1)
    .executeTakeFirst()

    console.log(result.numUpdatedRows) -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TR extends string

    -
    -

    Parameters

    -
      -
    • -
      table: TR
    -

    Returns UpdateQueryBuilder<DB, ExtractTableAlias<DB, TR>, ExtractTableAlias<DB, TR>, UpdateResult>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TR extends `${string} as ${string}`

    -
    -

    Parameters

    -
      -
    • -
      table: TR
    -

    Returns UpdateQueryBuilder<DB & PickTableWithAlias<DB, TR>, ExtractTableAlias<DB, TR>, ExtractTableAlias<DB, TR>, UpdateResult>

  • - -
  • -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      table: TR
    -

    Returns UpdateQueryBuilder<DrainOuterGeneric<{ [ C in any]: C extends ExtractAliasFromTableExpression<DB, TR> ? ExtractRowTypeFromTableExpression<DB, TR, C> : C extends keyof DB ? DB[C] : never }>, DrainOuterGeneric<ExtractAliasFromTableExpression<DB, TR>>, DrainOuterGeneric<ExtractAliasFromTableExpression<DB, TR>>, UpdateResult>

-
- -
    - -
  • -

    Creates a with query (Common Table Expression).

    - - -

    Examples

    -
    -
    await db
    .with('jennifers', (db) => db
    .selectFrom('person')
    .where('first_name', '=', 'Jennifer')
    .select(['id', 'age'])
    )
    .with('adult_jennifers', (db) => db
    .selectFrom('jennifers')
    .where('age', '>', 18)
    .select(['id', 'age'])
    )
    .selectFrom('adult_jennifers')
    .where('age', '<', 60)
    .selectAll()
    .execute() -
    -

    The CTE name can optionally specify column names in addition to -a name. In that case Kysely requires the expression to retun -rows with the same columns.

    -
    await db
    .with('jennifers(id, age)', (db) => db
    .selectFrom('person')
    .where('first_name', '=', 'Jennifer')
    // This is ok since we return columns with the same
    // names as specified by `jennifers(id, age)`.
    .select(['id', 'age'])
    )
    .selectFrom('jennifers')
    .selectAll()
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      N extends string

    • -
    • -

      E extends CommonTableExpression<DB, N>

    -
    -

    Parameters

    -
      -
    • -
      name: N
    • -
    • -
      expression: E
    -

    Returns QueryCreatorWithCommonTableExpression<DB, N, E>

-
- -
-
- -
    - -
  • -

    Creates a recursive with query (Common Table Expression).

    -

    See the with method for examples and more documentation.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      N extends string

    • -
    • -

      E extends RecursiveCommonTableExpression<DB, N>

    -
    -

    Parameters

    -
      -
    • -
      name: N
    • -
    • -
      expression: E
    -

    Returns QueryCreatorWithCommonTableExpression<DB, N, E>

-
- -
-
- -
    - -
  • -

    Returns a copy of this Kysely instance with tables added to its -database type.

    -

    This method only modifies the types and doesn't affect any of the -executed queries in any way.

    - - -

    Examples

    -
    -

    The following example adds and uses a temporary table:

    - -

    Example

    await db.schema
    .createTable('temp_table')
    .temporary()
    .addColumn('some_column', 'integer')
    .execute()

    const tempDb = db.withTables<{
    temp_table: {
    some_column: number
    }
    }>()

    await tempDb
    .insertInto('temp_table')
    .values({ some_column: 100 })
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T extends Record<string, Record<string, any>>

    -

    Returns Kysely<DB & T>

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/Log.html b/docs/classes/Log.html deleted file mode 100644 index a245093e3..000000000 --- a/docs/classes/Log.html +++ /dev/null @@ -1,137 +0,0 @@ -Log | kysely
-
- -
-
-
-
- -

Class Log

-
-

Hierarchy

-
    -
  • Log
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
    - -
  • -
    -

    Parameters

    -
      -
    • -
      level: "error" | "query"
    -

    Returns boolean

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/Migrator.html b/docs/classes/Migrator.html deleted file mode 100644 index e25b53785..000000000 --- a/docs/classes/Migrator.html +++ /dev/null @@ -1,209 +0,0 @@ -Migrator | kysely
-
- -
-
-
-
- -

Class Migrator

-
-

A class for running migrations.

- - -

Example

-
-

This example uses the FileMigrationProvider that reads migrations -files from a single folder. You can easily implement your own -MigrationProvider if you want to provide migrations some -other way.

-
import { promises as fs } from 'fs'
import path from 'path'

const migrator = new Migrator({
db,
provider: new FileMigrationProvider({
fs,
path,
// Path to the folder that contains all your migrations.
migrationFolder: 'some/path/to/migrations'
})
}) -
-
-
-

Hierarchy

-
    -
  • Migrator
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
    - -
  • -

    Migrate up/down to a specific migration.

    -

    This method returns a MigrationResultSet instance and never throws. -error holds the error if something went wrong. -results contains information about which migrations -were executed and which failed.

    - - -

    Examples

    -
    -
    await migrator.migrateTo('some_migration')
    -
    -

    If you specify the name of the first migration, this method migrates -down to the first migration, but doesn't run the down method of -the first migration. In case you want to migrate all the way down, -you can use a special constant NO_MIGRATIONS:

    -
    await migrator.migrateTo(NO_MIGRATIONS)
    -
    -
    -
    -

    Parameters

    -
    -

    Returns Promise<MigrationResultSet>

-
- -
    - -
  • -

    Runs all migrations that have not yet been run.

    -

    This method returns a MigrationResultSet instance and never throws. -error holds the error if something went wrong. -results contains information about which migrations -were executed and which failed. See the examples below.

    -

    This method goes through all possible migrations provided by the provider and runs the -ones whose names come alphabetically after the last migration that has been run. If the -list of executed migrations doesn't match the beginning of the list of possible migrations -an error is thrown.

    - - -

    Examples

    -
    -
    const db = new Kysely<Database>({
    dialect: new PostgresDialect({
    host: 'localhost',
    database: 'kysely_test',
    }),
    })

    const migrator = new Migrator({
    db,
    provider: new FileMigrationProvider(
    // Path to the folder that contains all your migrations.
    'some/path/to/migrations'
    )
    })

    const { error, results } = await migrator.migrateToLatest()

    results?.forEach((it) => {
    if (it.status === 'Success') {
    console.log(`migration "${it.migrationName}" was executed successfully`)
    } else if (it.status === 'Error') {
    console.error(`failed to execute migration "${it.migrationName}"`)
    }
    })

    if (error) {
    console.error('failed to run `migrateToLatest`')
    console.error(error)
    } -
    -
    -

    Returns Promise<MigrationResultSet>

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/MysqlAdapter.html b/docs/classes/MysqlAdapter.html deleted file mode 100644 index a75be5adb..000000000 --- a/docs/classes/MysqlAdapter.html +++ /dev/null @@ -1,174 +0,0 @@ -MysqlAdapter | kysely
-
- -
-
-
-
- -

Class MysqlAdapter

-
-

A basic implementation of DialectAdapter with sensible default values. -3rd party dialects can extend this instead of implementing the DialectAdapter -interface from scratch. That way all new settings will get default values when -they are added and there will be less breaking changes.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
    -
  • get supportsReturning(): boolean
  • -
  • -

    Whether or not this dialect supports the returning in inserts -updates and deletes.

    -
    -

    Returns boolean

-
- -
    -
  • get supportsTransactionalDdl(): boolean
  • -
  • -

    Whether or not this dialect supports transactional DDL.

    -

    If this is true, migrations are executed inside a transaction.

    -
    -

    Returns boolean

-
-

Methods

-
- -
    - -
  • -

    This method is used to acquire a lock for the migrations so that -it's not possible for two migration operations to run in parallel.

    -

    Most dialects have explicit locks that can be used, like advisory locks -in PostgreSQL and the get_lock function in MySQL.

    -

    If the dialect doesn't have explicit locks the lockTable -created by Kysely can be used instead. You can access it through the options object. -The lock table has two columns id and is_locked and there's only one row in the table -whose id is lockRowId. is_locked is an integer. Kysely -takes care of creating the lock table and inserting the one single row to it before this -method is executed. If the dialect supports schemas and the user has specified a custom -schema in their migration settings, the options object also contains the schema name in -lockTableSchema.

    -

    Here's an example of how you might implement this method for a dialect that doesn't -have explicit locks but supports FOR UPDATE row locks and transactional DDL:

    -
    {
    async acquireMigrationLock(db, options): Promise<void> {
    const queryDb = options.lockTableSchema
    ? db.withSchema(options.lockTableSchema)
    : db

    // Since our imaginary dialect supports transactional DDL and has
    // row locks, we can simply take a row lock here and it will guarantee
    // all subsequent calls to this method from other transactions will
    // wait until this transaction finishes.
    await queryDb
    .selectFrom(options.lockTable)
    .selectAll()
    .where('id', '=', options.lockRowId)
    .forUpdate()
    .execute()
    }
    } -
    -

    If supportsTransactionalDdl is true then the db passed to this method -is a transaction inside which the migrations will be executed. Otherwise -db is a single connection (session) that will be used to execute the -migrations.

    -
    -
    -

    Parameters

    -
    -

    Returns Promise<void>

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/MysqlDialect.html b/docs/classes/MysqlDialect.html deleted file mode 100644 index ccef82479..000000000 --- a/docs/classes/MysqlDialect.html +++ /dev/null @@ -1,154 +0,0 @@ -MysqlDialect | kysely
-
- -
-
-
-
- -

Class MysqlDialect

-
-

MySQL dialect that uses the mysql2 library.

-

The constructor takes an instance of MysqlDialectConfig.

-
import { createPool } from 'mysql2'

new MysqlDialect({
pool: createPool({
database: 'some_db',
host: 'localhost',
})
}) -
-

If you want the pool to only be created once it's first used, pool -can be a function:

-
import { createPool } from 'mysql2'

new MysqlDialect({
pool: async () => createPool({
database: 'some_db',
host: 'localhost',
})
}) -
-
-
-

Hierarchy

-
    -
  • MysqlDialect
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/MysqlDriver.html b/docs/classes/MysqlDriver.html deleted file mode 100644 index 41ecfb0ea..000000000 --- a/docs/classes/MysqlDriver.html +++ /dev/null @@ -1,203 +0,0 @@ -MysqlDriver | kysely
-
- -
-
-
-
- -

Class MysqlDriver

-
-

A Driver creates and releases database connections -and is also responsible for connection pooling (if the dialect supports pooling).

-
-
-

Hierarchy

-
    -
  • MysqlDriver
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Initializes the driver.

    -

    After calling this method the driver should be usable and acquireConnection etc. -methods should be callable.

    -
    -

    Returns Promise<void>

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/MysqlIntrospector.html b/docs/classes/MysqlIntrospector.html deleted file mode 100644 index 6d90de580..000000000 --- a/docs/classes/MysqlIntrospector.html +++ /dev/null @@ -1,138 +0,0 @@ -MysqlIntrospector | kysely
-
- -
-
-
-
- -

Class MysqlIntrospector

-
-

An interface for getting the database metadata (names of the tables and columns etc.)

-
-
-

Hierarchy

-
    -
  • MysqlIntrospector
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/MysqlQueryCompiler.html b/docs/classes/MysqlQueryCompiler.html deleted file mode 100644 index 8969fbecf..000000000 --- a/docs/classes/MysqlQueryCompiler.html +++ /dev/null @@ -1,1692 +0,0 @@ -MysqlQueryCompiler | kysely
-
- -
-
-
-
- -

Class MysqlQueryCompiler

-
-

a QueryCompiler compiles a query expressed as a tree of OperationNodes into SQL.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
-
-

Properties

-
-
-

Accessors

-
-
-

Methods

-
addParameter -append -appendImmediateValue -appendValue -compileDistinctOn -compileList -compileQuery -compileUnwrappedIdentifier -getAutoIncrement -getCurrentParameterPlaceholder -getExplainOptionAssignment -getExplainOptionsDelimiter -getLeftExplainOptionsWrapper -getLeftIdentifierWrapper -getRightExplainOptionsWrapper -getRightIdentifierWrapper -getSql -isMinusOperator -sanitizeIdentifier -visitAddColumn -visitAddConstraint -visitAggregateFunction -visitAlias -visitAlterColumn -visitAlterTable -visitAnd -visitBinaryOperation -visitCase -visitCheckConstraint -visitColumn -visitColumnDefinition -visitColumnUpdate -visitCommonTableExpression -visitCommonTableExpressionName -visitCreateIndex -visitCreateSchema -visitCreateTable -visitCreateType -visitCreateView -visitDataType -visitDefaultInsertValue -visitDefaultValue -visitDeleteQuery -visitDropColumn -visitDropConstraint -visitDropIndex -visitDropSchema -visitDropTable -visitDropType -visitDropView -visitExplain -visitForeignKeyConstraint -visitFrom -visitFunction -visitGenerated -visitGroupBy -visitGroupByItem -visitHaving -visitIdentifier -visitInsertQuery -visitJoin -visitLimit -visitList -visitModifyColumn -visitNode -visitOffset -visitOn -visitOnConflict -visitOnDuplicateKey -visitOperator -visitOr -visitOrderBy -visitOrderByItem -visitOver -visitParens -visitPartitionBy -visitPartitionByItem -visitPrimaryKeyConstraint -visitPrimitiveValueList -visitRaw -visitReference -visitReferences -visitRenameColumn -visitReturning -visitSchemableIdentifier -visitSelectAll -visitSelectModifier -visitSelectQuery -visitSelection -visitSetOperation -visitTable -visitUnaryOperation -visitUniqueConstraint -visitUpdateQuery -visitUsing -visitValue -visitValueList -visitValues -visitWhen -visitWhere -visitWith -
-
-

Constructors

-
- -
-
-

Properties

-
- -
nodeStack: OperationNode[] = []
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/NoResultError.html b/docs/classes/NoResultError.html deleted file mode 100644 index 2afe5d1a5..000000000 --- a/docs/classes/NoResultError.html +++ /dev/null @@ -1,184 +0,0 @@ -NoResultError | kysely
-
- -
-
-
-
- -

Class NoResultError

-
-

Hierarchy

-
    -
  • Error -
      -
    • NoResultError
-
-
-
- -
-
-

Constructors

-
-
-

Properties

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Properties

-
- -
cause?: unknown
-
- -
message: string
-
- -
name: string
-
- -
node: QueryNode
-

The operation node tree of the query that was executed.

-
-
- -
stack?: string
-
- -
prepareStackTrace?: ((err: Error, stackTraces: CallSite[]) => any)
-
-

Type declaration

-
-
- -
stackTraceLimit: number
-
-

Methods

-
- -
    - -
  • -

    Create .stack property on a target object

    -
    -
    -

    Parameters

    -
      -
    • -
      targetObject: object
    • -
    • -
      Optional constructorOpt: Function
    -

    Returns void

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/NoopQueryExecutor.html b/docs/classes/NoopQueryExecutor.html deleted file mode 100644 index 2628f59a6..000000000 --- a/docs/classes/NoopQueryExecutor.html +++ /dev/null @@ -1,283 +0,0 @@ -NoopQueryExecutor | kysely
-
- -
-
-
-
- -

Class NoopQueryExecutor

-
-

A QueryExecutor subclass that can be used when you don't -have a QueryCompiler, ConnectionProvider or any -other needed things to actually execute queries.

-
-
-

Hierarchy

-
    -
  • QueryExecutorBase -
      -
    • NoopQueryExecutor
-
-
-
- -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/OnConflictBuilder.html b/docs/classes/OnConflictBuilder.html deleted file mode 100644 index 56252cc51..000000000 --- a/docs/classes/OnConflictBuilder.html +++ /dev/null @@ -1,511 +0,0 @@ -OnConflictBuilder | kysely
-
- -
-
-
-
- -

Class OnConflictBuilder<DB, TB>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-

Hierarchy

-
    -
  • OnConflictBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/OnConflictDoNothingBuilder.html b/docs/classes/OnConflictDoNothingBuilder.html deleted file mode 100644 index edeb48e20..000000000 --- a/docs/classes/OnConflictDoNothingBuilder.html +++ /dev/null @@ -1,109 +0,0 @@ -OnConflictDoNothingBuilder | kysely
-
- -
-
-
-
- -

Class OnConflictDoNothingBuilder<DB, TB>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-

Hierarchy

-
    -
  • OnConflictDoNothingBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/OnConflictUpdateBuilder.html b/docs/classes/OnConflictUpdateBuilder.html deleted file mode 100644 index f9123cd31..000000000 --- a/docs/classes/OnConflictUpdateBuilder.html +++ /dev/null @@ -1,394 +0,0 @@ -OnConflictUpdateBuilder | kysely
-
- -
-
-
-
- -

Class OnConflictUpdateBuilder<DB, TB>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-

Hierarchy

-
    -
  • OnConflictUpdateBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/OperationNodeTransformer.html b/docs/classes/OperationNodeTransformer.html deleted file mode 100644 index 2446caf99..000000000 --- a/docs/classes/OperationNodeTransformer.html +++ /dev/null @@ -1,1373 +0,0 @@ -OperationNodeTransformer | kysely
-
- -
-
-
-
- -

Class OperationNodeTransformer

-
-

Transforms an operation node tree into another one.

-

Kysely queries are expressed internally as a tree of objects (operation nodes). -OperationNodeTransformer takes such a tree as its input and returns a -transformed deep copy of it. By default the OperationNodeTransformer -does nothing. You need to override one or more methods to make it do -something.

-

There's a method for each node type. For example if you'd like to convert -each identifier (table name, column name, alias etc.) from camelCase to -snake_case, you'd do something like this:

-
class CamelCaseTransformer extends OperationNodeTransformer {
transformIdentifier(node: IdentifierNode): IdentifierNode {
node = super.transformIdentifier(node),

return {
...node,
name: snakeCase(node.name),
}
}
}

const transformer = new CamelCaseTransformer()
const tree = transformer.transformNode(tree) -
-
-
-

Hierarchy

-
    -
  • OperationNodeTransformer
-
-
-
- -
-
-

Constructors

-
-
-

Properties

-
-
-

Methods

-
transformAddColumn -transformAddConstraint -transformAggregateFunction -transformAlias -transformAlterColumn -transformAlterTable -transformAnd -transformBinaryOperation -transformCase -transformCheckConstraint -transformColumn -transformColumnDefinition -transformColumnUpdate -transformCommonTableExpression -transformCommonTableExpressionName -transformCreateIndex -transformCreateSchema -transformCreateTable -transformCreateType -transformCreateView -transformDataType -transformDefaultInsertValue -transformDefaultValue -transformDeleteQuery -transformDropColumn -transformDropConstraint -transformDropIndex -transformDropSchema -transformDropTable -transformDropType -transformDropView -transformExplain -transformForeignKeyConstraint -transformFrom -transformFunction -transformGenerated -transformGroupBy -transformGroupByItem -transformHaving -transformIdentifier -transformInsertQuery -transformJoin -transformLimit -transformList -transformModifyColumn -transformNode -transformNodeImpl -transformNodeList -transformOffset -transformOn -transformOnConflict -transformOnDuplicateKey -transformOperator -transformOr -transformOrderBy -transformOrderByItem -transformOver -transformParens -transformPartitionBy -transformPartitionByItem -transformPrimaryKeyConstraint -transformPrimitiveValueList -transformRaw -transformReference -transformReferences -transformRenameColumn -transformReturning -transformSchemableIdentifier -transformSelectAll -transformSelectModifier -transformSelectQuery -transformSelection -transformSetOperation -transformTable -transformUnaryOperation -transformUniqueConstraint -transformUpdateQuery -transformUsing -transformValue -transformValueList -transformValues -transformWhen -transformWhere -transformWith -
-
-

Constructors

-
- -
-
-

Properties

-
- -
nodeStack: OperationNode[] = []
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -
    -

    Parameters

    -
      -
    • -
      node: CommonTableExpressionNameNode
    -

    Returns CommonTableExpressionNameNode

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/OperationNodeVisitor.html b/docs/classes/OperationNodeVisitor.html deleted file mode 100644 index c041cbdd0..000000000 --- a/docs/classes/OperationNodeVisitor.html +++ /dev/null @@ -1,1332 +0,0 @@ -OperationNodeVisitor | kysely
-
- -
-
-
-
- -

Class OperationNodeVisitorAbstract

-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Properties

-
- -
nodeStack: OperationNode[] = []
-
-

Accessors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/PostgresAdapter.html b/docs/classes/PostgresAdapter.html deleted file mode 100644 index 36e920aef..000000000 --- a/docs/classes/PostgresAdapter.html +++ /dev/null @@ -1,169 +0,0 @@ -PostgresAdapter | kysely
-
- -
-
-
-
- -

Class PostgresAdapter

-
-

A basic implementation of DialectAdapter with sensible default values. -3rd party dialects can extend this instead of implementing the DialectAdapter -interface from scratch. That way all new settings will get default values when -they are added and there will be less breaking changes.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
    -
  • get supportsReturning(): boolean
  • -
  • -

    Whether or not this dialect supports the returning in inserts -updates and deletes.

    -
    -

    Returns boolean

-
- -
    -
  • get supportsTransactionalDdl(): boolean
  • -
  • -

    Whether or not this dialect supports transactional DDL.

    -

    If this is true, migrations are executed inside a transaction.

    -
    -

    Returns boolean

-
-

Methods

-
- -
    - -
  • -

    This method is used to acquire a lock for the migrations so that -it's not possible for two migration operations to run in parallel.

    -

    Most dialects have explicit locks that can be used, like advisory locks -in PostgreSQL and the get_lock function in MySQL.

    -

    If the dialect doesn't have explicit locks the lockTable -created by Kysely can be used instead. You can access it through the options object. -The lock table has two columns id and is_locked and there's only one row in the table -whose id is lockRowId. is_locked is an integer. Kysely -takes care of creating the lock table and inserting the one single row to it before this -method is executed. If the dialect supports schemas and the user has specified a custom -schema in their migration settings, the options object also contains the schema name in -lockTableSchema.

    -

    Here's an example of how you might implement this method for a dialect that doesn't -have explicit locks but supports FOR UPDATE row locks and transactional DDL:

    -
    {
    async acquireMigrationLock(db, options): Promise<void> {
    const queryDb = options.lockTableSchema
    ? db.withSchema(options.lockTableSchema)
    : db

    // Since our imaginary dialect supports transactional DDL and has
    // row locks, we can simply take a row lock here and it will guarantee
    // all subsequent calls to this method from other transactions will
    // wait until this transaction finishes.
    await queryDb
    .selectFrom(options.lockTable)
    .selectAll()
    .where('id', '=', options.lockRowId)
    .forUpdate()
    .execute()
    }
    } -
    -

    If supportsTransactionalDdl is true then the db passed to this method -is a transaction inside which the migrations will be executed. Otherwise -db is a single connection (session) that will be used to execute the -migrations.

    -
    -
    -

    Parameters

    -
    -

    Returns Promise<void>

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/PostgresDialect.html b/docs/classes/PostgresDialect.html deleted file mode 100644 index 4f47770aa..000000000 --- a/docs/classes/PostgresDialect.html +++ /dev/null @@ -1,154 +0,0 @@ -PostgresDialect | kysely
-
- -
-
-
-
- -

Class PostgresDialect

-
-

PostgreSQL dialect that uses the pg library.

-

The constructor takes an instance of PostgresDialectConfig.

-
importPool } from 'pg'

new PostgresDialect({
pool: new Pool({
database: 'some_db',
host: 'localhost',
})
}) -
-

If you want the pool to only be created once it's first used, pool -can be a function:

-
importPool } from 'pg'

new PostgresDialect({
pool: async () => new Pool({
database: 'some_db',
host: 'localhost',
})
}) -
-
-
-

Hierarchy

-
    -
  • PostgresDialect
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/PostgresDriver.html b/docs/classes/PostgresDriver.html deleted file mode 100644 index fbc8231c5..000000000 --- a/docs/classes/PostgresDriver.html +++ /dev/null @@ -1,203 +0,0 @@ -PostgresDriver | kysely
-
- -
-
-
-
- -

Class PostgresDriver

-
-

A Driver creates and releases database connections -and is also responsible for connection pooling (if the dialect supports pooling).

-
-
-

Hierarchy

-
    -
  • PostgresDriver
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Initializes the driver.

    -

    After calling this method the driver should be usable and acquireConnection etc. -methods should be callable.

    -
    -

    Returns Promise<void>

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/PostgresIntrospector.html b/docs/classes/PostgresIntrospector.html deleted file mode 100644 index 2cf9dbb5d..000000000 --- a/docs/classes/PostgresIntrospector.html +++ /dev/null @@ -1,138 +0,0 @@ -PostgresIntrospector | kysely
-
- -
-
-
-
- -

Class PostgresIntrospector

-
-

An interface for getting the database metadata (names of the tables and columns etc.)

-
-
-

Hierarchy

-
    -
  • PostgresIntrospector
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/PostgresQueryCompiler.html b/docs/classes/PostgresQueryCompiler.html deleted file mode 100644 index 0026ef1d2..000000000 --- a/docs/classes/PostgresQueryCompiler.html +++ /dev/null @@ -1,1692 +0,0 @@ -PostgresQueryCompiler | kysely
-
- -
-
-
-
- -

Class PostgresQueryCompiler

-
-

a QueryCompiler compiles a query expressed as a tree of OperationNodes into SQL.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
-
-

Properties

-
-
-

Accessors

-
-
-

Methods

-
addParameter -append -appendImmediateValue -appendValue -compileDistinctOn -compileList -compileQuery -compileUnwrappedIdentifier -getAutoIncrement -getCurrentParameterPlaceholder -getExplainOptionAssignment -getExplainOptionsDelimiter -getLeftExplainOptionsWrapper -getLeftIdentifierWrapper -getRightExplainOptionsWrapper -getRightIdentifierWrapper -getSql -isMinusOperator -sanitizeIdentifier -visitAddColumn -visitAddConstraint -visitAggregateFunction -visitAlias -visitAlterColumn -visitAlterTable -visitAnd -visitBinaryOperation -visitCase -visitCheckConstraint -visitColumn -visitColumnDefinition -visitColumnUpdate -visitCommonTableExpression -visitCommonTableExpressionName -visitCreateIndex -visitCreateSchema -visitCreateTable -visitCreateType -visitCreateView -visitDataType -visitDefaultInsertValue -visitDefaultValue -visitDeleteQuery -visitDropColumn -visitDropConstraint -visitDropIndex -visitDropSchema -visitDropTable -visitDropType -visitDropView -visitExplain -visitForeignKeyConstraint -visitFrom -visitFunction -visitGenerated -visitGroupBy -visitGroupByItem -visitHaving -visitIdentifier -visitInsertQuery -visitJoin -visitLimit -visitList -visitModifyColumn -visitNode -visitOffset -visitOn -visitOnConflict -visitOnDuplicateKey -visitOperator -visitOr -visitOrderBy -visitOrderByItem -visitOver -visitParens -visitPartitionBy -visitPartitionByItem -visitPrimaryKeyConstraint -visitPrimitiveValueList -visitRaw -visitReference -visitReferences -visitRenameColumn -visitReturning -visitSchemableIdentifier -visitSelectAll -visitSelectModifier -visitSelectQuery -visitSelection -visitSetOperation -visitTable -visitUnaryOperation -visitUniqueConstraint -visitUpdateQuery -visitUsing -visitValue -visitValueList -visitValues -visitWhen -visitWhere -visitWith -
-
-

Constructors

-
- -
-
-

Properties

-
- -
nodeStack: OperationNode[] = []
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/QueryCreator.html b/docs/classes/QueryCreator.html deleted file mode 100644 index 2cc47e6cf..000000000 --- a/docs/classes/QueryCreator.html +++ /dev/null @@ -1,565 +0,0 @@ -QueryCreator | kysely
-
- -
-
-
-
- -

Class QueryCreator<DB>

-
-

Type Parameters

-
    -
  • -

    DB

-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    Creates a delete query.

    -

    See the where method for examples on how to specify -a where clause for the delete operation.

    -

    The return value of the query is an instance of DeleteResult.

    - - -

    Examples

    -
    -

    Deleting person with id 1:

    -
    const result = await db
    .deleteFrom('person')
    .where('person.id', '=', 1)
    .executeTakeFirst()

    console.log(result.numDeletedRows) -
    -

    The generated SQL (PostgreSQL):

    -
    delete from "person" where "person"."id" = $1
    -
    -

    Some databases such as MySQL support deleting from multiple tables:

    -
    const result = await db
    .deleteFrom(['person', 'pet'])
    .using('person')
    .innerJoin('pet', 'pet.owner_id', '=', 'person.id')
    .where('person.id', '=', 1)
    .executeTakeFirst() -
    -

    The generated SQL (MySQL):

    -
    delete from `person`, `pet`
    using `person`
    inner join `pet` on `pet`.`owner_id` = `person`.`id`
    where `person`.`id` = ? -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TR extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TR[]
    -

    Returns DeleteQueryBuilder<DB, ExtractTableAlias<DB, TR>, DeleteResult>

  • - -
  • -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      tables: TR[]
    -

    Returns DeleteQueryBuilder<From<DB, TR>, FromTables<DB, never, TR>, DeleteResult>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TR extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TR
    -

    Returns DeleteQueryBuilder<DB, ExtractTableAlias<DB, TR>, DeleteResult>

  • - -
  • -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      table: TR
    -

    Returns DeleteQueryBuilder<From<DB, TR>, FromTables<DB, never, TR>, DeleteResult>

-
- -
    - -
  • -

    Creates an insert query.

    -

    The return value of this query is an instance of InsertResult. InsertResult -has the insertId field that holds the auto incremented id of -the inserted row if the db returned one.

    -

    See the values method for more info and examples. Also see -the returning method for a way to return columns -on supported databases like PostgreSQL.

    - - -

    Examples

    -
    -
    const result = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .executeTakeFirst()

    console.log(result.insertId) -
    -

    Some databases like PostgreSQL support the returning method:

    -
    const { id } = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .returning('id')
    .executeTakeFirst() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T extends string

    -
    -

    Parameters

    -
      -
    • -
      table: T
    -

    Returns InsertQueryBuilder<DB, T, InsertResult>

-
- -
    - -
  • -

    Creates a replace query.

    -

    A MySQL-only statement similar to onDuplicateKeyUpdate -that deletes and inserts values on collision instead of updating existing rows.

    -

    The return value of this query is an instance of InsertResult. InsertResult -has the insertId field that holds the auto incremented id of -the inserted row if the db returned one.

    -

    See the values method for more info and examples.

    - - -

    Examples

    -
    -
    const result = await db
    .replaceInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .executeTakeFirst()

    console.log(result.insertId) -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T extends string

    -
    -

    Parameters

    -
      -
    • -
      table: T
    -

    Returns InsertQueryBuilder<DB, T, InsertResult>

-
- -
    - -
  • -

    Creates a select query builder for the given table or tables.

    -

    The tables passed to this method are built as the query's from clause.

    - - -

    Examples

    -
    -

    Create a select query for one table:

    -
    db.selectFrom('person').selectAll()
    -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "person"
    -
    -

    Create a select query for one table with an alias:

    -
    const persons = await db.selectFrom('person as p')
    .select(['p.id', 'first_name'])
    .execute()

    console.log(persons[0].id) -
    -

    The generated SQL (PostgreSQL):

    -
    select "p"."id", "first_name" from "person" as "p"
    -
    -

    Create a select query from a subquery:

    -
    const persons = await db.selectFrom(
    (eb) => eb.selectFrom('person').select('person.id as identifier').as('p')
    )
    .select('p.identifier')
    .execute()

    console.log(persons[0].identifier) -
    -

    The generated SQL (PostgreSQL):

    -
    select "p"."identifier",
    from (
    select "person"."id" as "identifier" from "person"
    ) as p -
    -

    Create a select query from raw sql:

    -
    importsql } from 'kysely'

    const items = await db
    .selectFrom(sql<{ one: number }>`(select 1 as one)`.as('q'))
    .select('q.one')
    .execute()

    console.log(items[0].one) -
    -

    The generated SQL (PostgreSQL):

    -
    select "q"."one",
    from (
    select 1 as one
    ) as q -
    -

    When you use the sql tag you need to also provide the result type of the -raw snippet / query so that Kysely can figure out what columns are -available for the rest of the query.

    -

    The selectFrom method also accepts an array for multiple tables. All -the above examples can also be used in an array.

    -
    importsql } from 'kysely'

    const items = await db.selectFrom([
    'person as p',
    db.selectFrom('pet').select('pet.species').as('a'),
    sql<{ one: number }>`(select 1 as one)`.as('q')
    ])
    .select(['p.id', 'a.species', 'q.one'])
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select "p".id, "a"."species", "q"."one"
    from
    "person" as "p",
    (select "pet"."species" from "pet") as a,
    (select 1 as one) as "q" -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TE extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TE[]
    -

    Returns SelectQueryBuilder<DB, ExtractTableAlias<DB, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, keyof DB>

    -
    -

    Parameters

    -
      -
    • -
      from: TE[]
    -

    Returns SelectQueryBuilder<From<DB, TE>, FromTables<DB, never, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TE
    -

    Returns SelectQueryBuilder<DB, ExtractTableAlias<DB, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends `${string} as ${string}`

    -
    -

    Parameters

    -
      -
    • -
      from: TE
    -

    Returns SelectQueryBuilder<DB & PickTableWithAlias<DB, TE>, ExtractTableAlias<DB, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, keyof DB>

    -
    -

    Parameters

    -
      -
    • -
      from: TE
    -

    Returns SelectQueryBuilder<From<DB, TE>, FromTables<DB, never, TE>, {}>

-
- -
    - -
  • -

    Creates an update query.

    -

    See the where method for examples on how to specify -a where clause for the update operation.

    -

    See the set method for examples on how to -specify the updates.

    -

    The return value of the query is an UpdateResult.

    - - -

    Examples

    -
    -
    const result = await db
    .updateTable('person')
    .set({ first_name: 'Jennifer' })
    .where('person.id', '=', 1)
    .executeTakeFirst()

    console.log(result.numUpdatedRows) -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TR extends string

    -
    -

    Parameters

    -
      -
    • -
      table: TR
    -

    Returns UpdateQueryBuilder<DB, ExtractTableAlias<DB, TR>, ExtractTableAlias<DB, TR>, UpdateResult>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TR extends `${string} as ${string}`

    -
    -

    Parameters

    -
      -
    • -
      table: TR
    -

    Returns UpdateQueryBuilder<DB & PickTableWithAlias<DB, TR>, ExtractTableAlias<DB, TR>, ExtractTableAlias<DB, TR>, UpdateResult>

  • - -
  • -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      table: TR
    -

    Returns UpdateQueryBuilder<From<DB, TR>, FromTables<DB, never, TR>, FromTables<DB, never, TR>, UpdateResult>

-
- -
    - -
  • -

    Creates a with query (Common Table Expression).

    - - -

    Examples

    -
    -
    await db
    .with('jennifers', (db) => db
    .selectFrom('person')
    .where('first_name', '=', 'Jennifer')
    .select(['id', 'age'])
    )
    .with('adult_jennifers', (db) => db
    .selectFrom('jennifers')
    .where('age', '>', 18)
    .select(['id', 'age'])
    )
    .selectFrom('adult_jennifers')
    .where('age', '<', 60)
    .selectAll()
    .execute() -
    -

    The CTE name can optionally specify column names in addition to -a name. In that case Kysely requires the expression to retun -rows with the same columns.

    -
    await db
    .with('jennifers(id, age)', (db) => db
    .selectFrom('person')
    .where('first_name', '=', 'Jennifer')
    // This is ok since we return columns with the same
    // names as specified by `jennifers(id, age)`.
    .select(['id', 'age'])
    )
    .selectFrom('jennifers')
    .selectAll()
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      N extends string

    • -
    • -

      E extends CommonTableExpression<DB, N>

    -
    -

    Parameters

    -
      -
    • -
      name: N
    • -
    • -
      expression: E
    -

    Returns QueryCreatorWithCommonTableExpression<DB, N, E>

-
- -
-
- -
    - -
  • -

    Creates a recursive with query (Common Table Expression).

    -

    See the with method for examples and more documentation.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      N extends string

    • -
    • -

      E extends RecursiveCommonTableExpression<DB, N>

    -
    -

    Parameters

    -
      -
    • -
      name: N
    • -
    • -
      expression: E
    -

    Returns QueryCreatorWithCommonTableExpression<DB, N, E>

-
- -
    - -
  • -

    Sets the schema to be used for all table references that don't explicitly -specify a schema.

    -

    This only affects the query created through the builder returned from -this method and doesn't modify the db instance.

    -

    See this recipe -for a more detailed explanation.

    - - -

    Examples

    -
    -
    await db
    .withSchema('mammals')
    .selectFrom('pet')
    .selectAll()
    .innerJoin('public.person', 'public.person.id', 'pet.owner_id')
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "mammals"."pet"
    inner join "public"."person"
    on "public"."person"."id" = "mammals"."pet"."owner_id" -
    -

    withSchema is smart enough to not add schema for aliases, -common table expressions or other places where the schema -doesn't belong to:

    -
    await db
    .withSchema('mammals')
    .selectFrom('pet as p')
    .select('p.name')
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select "p"."name" from "mammals"."pet" as "p"
    -
    -
    -
    -

    Parameters

    -
      -
    • -
      schema: string
    -

    Returns QueryCreator<DB>

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/RawBuilder.html b/docs/classes/RawBuilder.html deleted file mode 100644 index 52c18cb4a..000000000 --- a/docs/classes/RawBuilder.html +++ /dev/null @@ -1,251 +0,0 @@ -RawBuilder | kysely
-
- -
-
-
-
- -

Class RawBuilder<O>

-
-

An instance of this class can be used to create raw SQL snippets or queries.

-

You shouldn't need to create RawBuilder instances directly. Instead you should -use the sql template tag.

-
-
-

Type Parameters

-
    -
  • -

    O

-
-

Hierarchy

-
    -
  • RawBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    Change the output type of the raw expression.

    -

    This method call doesn't change the SQL in any way. This methods simply -returns a copy of this RawBuilder with a new output type.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -

    Returns RawBuilder<T>

-
- -
    - -
  • -

    Returns an aliased version of the SQL expression.

    -

    In addition to slapping as "the_alias" to the end of the SQL, -this method also provides strict typing:

    -
    const result = await db
    .selectFrom('person')
    .select(
    sql<string>`concat(first_name, ' ', last_name)`.as('full_name')
    )
    .executeTakeFirstOrThrow()

    // `full_name: string` field exists in the result type.
    console.log(result.full_name) -
    -

    The generated SQL (PostgreSQL):

    -
    select concat(first_name, ' ', last_name) as "full_name"
    from "person" -
    -

    You can also pass in a raw SQL snippet but in that case you must -provide the alias as the only type argument:

    -
    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'])
    ) -
    -

    The generated SQL (PostgreSQL):

    -
    insert into "person" ("first_name", "last_name")
    from (values (1, 'foo')) as t(a, b)
    select "t"."a", "t"."b" -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      A extends string

    -
    -

    Parameters

    -
      -
    • -
      alias: A
    -

    Returns AliasedRawBuilder<O, A>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      A extends string

    -
    -

    Parameters

    -
    -

    Returns AliasedRawBuilder<O, A>

-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Creates the OperationNode that describes how to compile this expression into SQL.

    -

    If you are creating a custom expression, it's often easiest to use the sql -template tag to build the node:

    -
    class SomeExpression<T> implements Expression<T> {
    toOperationNode(): OperationNode {
    return sql`some sql here`.toOperationNode()
    }
    } -
    -
    -

    Returns RawNode

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/SchemaModule.html b/docs/classes/SchemaModule.html deleted file mode 100644 index f4a6055a7..000000000 --- a/docs/classes/SchemaModule.html +++ /dev/null @@ -1,403 +0,0 @@ -SchemaModule | kysely
-
- -
-
-
-
- -

Class SchemaModule

-
-

Provides methods for building database schema.

-
-
-

Hierarchy

-
    -
  • SchemaModule
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Create a new table.

    - - -

    Examples

    -
    -

    This example creates a new table with columns id, first_name, -last_name and gender:

    -
    await db.schema
    .createTable('person')
    .addColumn('id', 'integer', col => col.primaryKey().autoIncrement())
    .addColumn('first_name', 'varchar', col => col.notNull())
    .addColumn('last_name', 'varchar', col => col.notNull())
    .addColumn('gender', 'varchar')
    .execute() -
    -

    This example creates a table with a foreign key. Not all database -engines support column-level foreign key constraint definitions. -For example if you are using MySQL 5.X see the next example after -this one.

    -
    await db.schema
    .createTable('pet')
    .addColumn('id', 'integer', col => col.primaryKey().autoIncrement())
    .addColumn('owner_id', 'integer', col => col
    .references('person.id')
    .onDelete('cascade')
    )
    .execute() -
    -

    This example adds a foreign key constraint for a columns just -like the previous example, but using a table-level statement. -On MySQL 5.X you need to define foreign key constraints like -this:

    -
    await db.schema
    .createTable('pet')
    .addColumn('id', 'integer', col => col.primaryKey().autoIncrement())
    .addColumn('owner_id', 'integer')
    .addForeignKeyConstraint(
    'pet_owner_id_foreign', ['owner_id'], 'person', ['id'],
    (constraint) => constraint.onDelete('cascade')
    )
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TB extends string

    -
    -

    Parameters

    -
      -
    • -
      table: TB
    -

    Returns CreateTableBuilder<TB, never>

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/SelectQueryBuilder.html b/docs/classes/SelectQueryBuilder.html deleted file mode 100644 index a83e38f7a..000000000 --- a/docs/classes/SelectQueryBuilder.html +++ /dev/null @@ -1,2216 +0,0 @@ -SelectQueryBuilder | kysely
-
- -
-
-
-
- -

Class SelectQueryBuilder<DB, TB, O>

-
-

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 sql template tag implement it.

-
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.

-
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    O

-
-

Hierarchy

-
    -
  • SelectQueryBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    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

    -
    -
    const result = await db
    .with('first_and_last', (qb) => qb
    .selectFrom('person')
    .select(['first_name', 'last_name'])
    .$assertType<{ first_name: string, last_name: string }>()
    )
    .with('age', (qb) => qb
    .selectFrom('person')
    .select('age')
    .$assertType<{ age: number }>()
    )
    .selectFrom(['first_and_last', 'age'])
    .selectAll()
    .executeTakeFirstOrThrow() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -

    Returns O extends T ? SelectQueryBuilder<DB, TB, T> : KyselyTypeError<"$assertType() call failed: The type passed in is not equal to the output type of the query.">

-
- -
    - -
  • -

    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 $if method.

    - - -

    Examples

    -
    -

    The next example uses a helper function log to log a query:

    -
    function log<T extends Compilable>(qb: T): T {
    console.log(qb.compile())
    return qb
    }

    db.selectFrom('person')
    .selectAll()
    .$call(log)
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -
    -

    Parameters

    -
    -

    Returns T

-
- -
-
- -
    - -
  • -

    Call func(this) if condition is true.

    -

    NOTE: This method has an impact on typescript performance and it should only be used -when necessary. Remember that you can call most methods like where conditionally -like this:

    -
    let query = db.selectFrom('person').selectAll()

    if (firstName) {
    query = query.where('first_name', '=', firstName)
    }

    if (lastName) {
    query = query.where('last_name', '=', lastName)
    }

    const result = await query.execute() -
    -

    This method is mainly useful with optional selects. Any select or selectAll -method called inside the callback add optional fields to the result type. This is -because we can't know if those selections were actually made before running the code.

    -

    Also see this recipe

    - - -

    Examples

    -
    -
    async function getPerson(id: number, withLastName: boolean) {
    return await db
    .selectFrom('person')
    .select(['id', 'first_name'])
    .$if(withLastName, (qb) => qb.select('last_name'))
    .where('id', '=', id)
    .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 getPerson function is:

    -
    {
    id: number
    first_name: string
    last_name?: string
    } -
    -

    You can also call any other methods inside the callback:

    -
    const { count } = db.fn

    db.selectFrom('person')
    .select('person.id')
    .$if(filterByFirstName, (qb) => qb.where('first_name', '=', firstName))
    .$if(filterByPetCount, (qb) => qb
    .innerJoin('pet', 'pet.owner_id', 'person.id')
    .having(count('pet.id'), '>', petCountLimit)
    .groupBy('person.id')
    ) -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      O2

    -
    -

    Parameters

    -
    -

    Returns SelectQueryBuilder<DB, TB, O & Partial<O2>>

-
- -
    - -
  • -

    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 where, having -or JoinQueryBuilder.on.

    -

    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:

    -
    const person = await db.selectFrom('person')
    .where('nullable_column', 'is not', null)
    .selectAll()
    .executeTakeFirstOrThrow()

    if (person.nullable_column) {
    functionThatExpectsPersonWithNonNullValue(person)
    } -
    -

    Into this:

    -
    const person = await db.selectFrom('person')
    .where('nullable_column', 'is not', null)
    .selectAll()
    .$narrowType<{ nullable_column: string }>()
    .executeTakeFirstOrThrow()

    functionThatExpectsPersonWithNonNullValue(person) -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -

    Returns SelectQueryBuilder<DB, TB, NarrowPartial<O, T>>

-
- -
    - -
  • -

    Gives an alias for the query. This method is only useful for sub queries.

    - - -

    Examples

    -
    -
    const pets = await db.selectFrom('pet')
    .selectAll('pet')
    .select(
    (qb) => qb.selectFrom('person')
    .select('first_name')
    .whereRef('pet.owner_id', '=', 'person.id')
    .as('owner_first_name')
    )
    .execute()

    pets[0].owner_first_name -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      A extends string

    -
    -

    Parameters

    -
      -
    • -
      alias: A
    -

    Returns AliasedSelectQueryBuilder<DB, TB, O, A>

-
- -
    - -
  • -
    -

    Deprecated

    Use $assertType instead.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -

    Returns O extends T ? SelectQueryBuilder<DB, TB, T> : KyselyTypeError<"assertType() call failed: The type passed in is not equal to the output type of the query.">

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Adds distinct on expressions to the select clause.

    - - -

    Examples

    -
    -
    await db.selectFrom('person')
    .innerJoin('pet', 'pet.owner_id', 'person.id')
    .where('pet.name', '=', 'Doggo')
    .distinctOn('person.id')
    .selectAll('person')
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select distinct on ("person"."id") "person".*
    from "person"
    inner join "pet" on "pet"."owner_id" = "person"."id"
    where "pet"."name" = $1 -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      RE extends string | Expression<any> | DynamicReferenceBuilder<any> | SelectQueryBuilder<any, any, {}> | SelectQueryBuilderFactory<DB, TB, {}> | ExpressionFactory<DB, TB, any>

    -
    -

    Parameters

    -
      -
    • -
      selections: readonly RE[]
    -

    Returns SelectQueryBuilder<DB, TB, O>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      RE extends string | Expression<any> | DynamicReferenceBuilder<any> | SelectQueryBuilder<any, any, {}> | SelectQueryBuilderFactory<DB, TB, {}> | ExpressionFactory<DB, TB, any>

    -
    -

    Parameters

    -
      -
    • -
      selection: RE
    -

    Returns SelectQueryBuilder<DB, TB, O>

-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Executes the query and returns the first result or undefined if -the query returned no result.

    -
    -

    Returns Promise<SimplifySingleResult<O>>

-
- -
-
- -
    - -
  • -

    Executes query with explain statement before the main query.

    -
    const explained = await db
    .selectFrom('person')
    .where('gender', '=', 'female')
    .selectAll()
    .explain('json') -
    -

    The generated SQL (MySQL):

    -
    explain format=json select * from `person` where `gender` = ?
    -
    -

    You can also execute explain analyze statements.

    -
    import { sql } from 'kysely'

    const explained = await db
    .selectFrom('person')
    .where('gender', '=', 'female')
    .selectAll()
    .explain('json', sql`analyze`) -
    -

    The generated SQL (PostgreSQL):

    -
    explain (analyze, format json) select * from "person" where "gender" = $1
    -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      ER extends Record<string, any> = Record<string, any>

    -
    -

    Parameters

    -
    -

    Returns Promise<ER[]>

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Adds a group by clause to the query.

    - - -

    Examples

    -
    -
    importsql } from 'kysely'

    await db
    .selectFrom('person')
    .select([
    'first_name',
    sql`max(id)`.as('max_id')
    ])
    .groupBy('first_name')
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select "first_name", max(id)
    from "person"
    group by "first_name" -
    -

    groupBy also accepts an array:

    -
    importsql } from 'kysely'

    await db
    .selectFrom('person')
    .select([
    'first_name',
    'last_name',
    sql`max(id)`.as('max_id')
    ])
    .groupBy([
    'first_name',
    'last_name'
    ])
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select "first_name", "last_name", max(id)
    from "person"
    group by "first_name", "last_name" -
    -

    The group by expressions can also be subqueries or -raw sql expressions:

    -
    import { sql } from 'kysely'

    await db
    .selectFrom('person')
    .select([
    'first_name',
    'last_name',
    sql`max(id)`.as('max_id')
    ])
    .groupBy([
    sql`concat(first_name, last_name)`,
    (qb) => qb.selectFrom('pet').select('id').limit(1)
    ])
    .execute() -
    -

    dynamic.ref can be used to refer to columns not known at -compile time:

    -
    async function someQuery(groupBy: string) {
    const { ref } = db.dynamic

    return await db
    .selectFrom('person')
    .select('first_name')
    .groupBy(ref(groupBy))
    .execute()
    }

    someQuery('first_name') -
    -

    The generated SQL (PostgreSQL):

    -
    select "first_name"
    from "person"
    group by "first_name" -
    -
    -
    -

    Parameters

    -
      -
    • -
      groupBy: GroupByArg<DB, TB, O>
    -

    Returns SelectQueryBuilder<DB, TB, O>

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Joins another table to the query using an inner join.

    - - -

    Examples

    -
    -

    Simple usage by providing a table name and two columns to join:

    -
    const result = await db
    .selectFrom('person')
    .innerJoin('pet', 'pet.owner_id', 'person.id')
    // `select` needs to come after the call to `innerJoin` so
    // that you can select from the joined table.
    .select('person.id', 'pet.name')
    .execute()

    result[0].id
    result[0].name -
    -

    The generated SQL (PostgreSQL):

    -
    select "person"."id", "pet"."name"
    from "person"
    inner join "pet"
    on "pet"."owner_id" = "person"."id" -
    -

    You can give an alias for the joined table like this:

    -
    await db.selectFrom('person')
    .innerJoin('pet as p', 'p.owner_id', 'person.id')
    .where('p.name', '=', 'Doggo')
    .selectAll()
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select *
    from "person"
    inner join "pet" as "p"
    on "p"."owner_id" = "person"."id"
    where "p".name" = $1 -
    -

    You can provide a function as the second argument to get a join -builder for creating more complex joins. The join builder has a -bunch of on* methods for building the on clause of the join. -There's basically an equivalent for every where method -(on, onRef, onExists etc.). You can do all the same things -with the on method that you can with the corresponding where -method. See the where method documentation for more examples.

    -
    await db.selectFrom('person')
    .innerJoin(
    'pet',
    (join) => join
    .onRef('pet.owner_id', '=', 'person.id')
    .on('pet.name', '=', 'Doggo')
    )
    .selectAll()
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select *
    from "person"
    inner join "pet"
    on "pet"."owner_id" = "person"."id"
    and "pet"."name" = $1 -
    -

    You can join a subquery by providing a select query (or a callback) -as the first argument:

    -
    await db.selectFrom('person')
    .innerJoin(
    db.selectFrom('pet')
    .select(['owner_id', 'name'])
    .where('name', '=', 'Doggo')
    .as('doggos'),
    'doggos.owner_id',
    'person.id',
    )
    .selectAll()
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select *
    from "person"
    inner join (
    select "owner_id", "name"
    from "pet"
    where "name" = $1
    ) as "doggos"
    on "doggos"."owner_id" = "person"."id" -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, TB>

    • -
    • -

      K1 extends string

    • -
    • -

      K2 extends string

    -
    -

    Parameters

    -
      -
    • -
      table: TE
    • -
    • -
      k1: K1
    • -
    • -
      k2: K2
    -

    Returns SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>

  • - -
  • -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      table: TE
    • -
    • -
      callback: FN
    -

    Returns SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Adds a limit clause to the query.

    - - -

    Examples

    -
    -

    Select the first 10 rows of the result:

    -
    return await db
    .selectFrom('person')
    .select('first_name')
    .limit(10) -
    -

    Select rows from index 10 to index 19 of the result:

    -
    return await db
    .selectFrom('person')
    .select('first_name')
    .offset(10)
    .limit(10) -
    -
    -
    -

    Parameters

    -
      -
    • -
      limit: number
    -

    Returns SelectQueryBuilder<DB, TB, O>

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Adds an order by clause to the query.

    -

    orderBy calls are additive. To order by multiple columns, call orderBy -multiple times.

    -

    The first argument is the expression to order by and the second is the -order (asc or desc).

    - - -

    Examples

    -
    -
    await db
    .selectFrom('person')
    .select('person.first_name as fn')
    .orderBy('id')
    .orderBy('fn', 'desc')
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select "person"."first_name" as "fn"
    from "person"
    order by "id" asc, "fn" desc -
    -

    The order by expression can also be a raw sql expression or a subquery -in addition to column references:

    -
    importsql } 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`concat(first_name, last_name)`
    )
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    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:

    -
    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):

    -
    select "person"."first_name" as "fn"
    from "person"
    order by "fn" asc -
    -
    -
    -

    Parameters

    -
    -

    Returns SelectQueryBuilder<DB, TB, O>

-
- -
-
- -
    - -
  • -

    Adds a select statement to the query.

    -

    When a column (or any expression) is selected, Kysely adds its type to the return -type of the query. Kysely is smart enough to parse the selection names and types -from aliased columns, subqueries, raw expressions etc.

    -

    Kysely only allows you to select columns and expressions that exist and would -produce valid SQL. However, Kysely is not perfect and there may be cases where -the type inference doesn't work and you need to override it. You can always -use the dynamic module and the sql tag -to override the types.

    -

    Select calls are additive. Calling select('id').select('first_name') is the -same as calling select(['id', 'first_name']).

    -

    To select all columns of the query or specific tables see the -selectAll method.

    -

    See the $if method if you are looking for a way to add selections -based on a runtime condition.

    - - -

    Examples

    -
    -

    Select a single column:

    -
    const persons = await db
    .selectFrom('person')
    .select('id')
    .where('first_name', '=', 'Arnold')
    .execute()

    persons[0].id -
    -

    The generated SQL (PostgreSQL):

    -
    select "id" from "person" where "first_name" = $1
    -
    -

    Select a single column and specify a table:

    -
    const persons = await db
    .selectFrom(['person', 'pet'])
    .select('person.id')
    .execute()

    persons[0].id -
    -

    The generated SQL (PostgreSQL):

    -
    select "person"."id" from "person", "pet"
    -
    -

    Select multiple columns:

    -
    const persons = await db
    .selectFrom('person')
    .select(['person.id', 'first_name'])
    .execute()

    persons[0].id
    persons[0].first_name -
    -

    The generated SQL (PostgreSQL):

    -
    select "person"."id", "first_name" from "person"
    -
    -

    Aliased selections:

    -
    const persons = await db
    .selectFrom('person')
    .select([
    'person.first_name as fn',
    'person.last_name as ln'
    ])
    .execute()

    persons[0].fn
    persons[0].ln -
    -

    The generated SQL (PostgreSQL):

    -
    select
    "person"."first_name" as "fn",
    "person"."last_name" as "ln"
    from "person" -
    -

    You can also select arbitrary expression including subqueries and raw sql snippets. -When you do that, you need to give a name for the selections using the as method:

    -
    importsql } from 'kysely'

    const persons = await db.selectFrom('person')
    .select(({ selectFrom, or, cmpr }) => [
    // Select a correlated subquery
    selectFrom('pet')
    .whereRef('person.id', '=', 'pet.owner_id')
    .select('pet.name')
    .orderBy('pet.name')
    .limit(1)
    .as('first_pet_name'),

    // Build and select an expression using the expression builder
    or([
    cmpr('first_name', '=', 'Jennifer'),
    cmpr('first_name', '=', 'Arnold')
    ]).as('is_jennifer_or_arnold'),

    // Select a raw sql expression
    sql<string>`concat(first_name, ' ', last_name)`.as('full_name')
    ])
    .execute()

    persons[0].first_pet_name
    persons[0].is_jennifer_or_arnold
    persons[0].full_name -
    -

    The generated SQL (PostgreSQL):

    -
    select
    (
    select "pet"."name"
    from "pet"
    where "person"."id" = "pet"."owner_id"
    order by "pet"."name"
    limit $1
    ) as "pet_name",
    ("first_name" = $2 or "first_name" = $3) as "jennifer_or_arnold",
    concat(first_name, ' ', last_name) as "full_name"
    from "person" -
    -

    In case you use the sql tag you need to specify the type of the expression -(in this example string).

    -

    All the examples above assume you know the column names at compile time. -While it's better to build your code like that (that way you also know -the types) sometimes it's not possible or you just prefer to write more -dynamic code. -

    -In this example, we use the dynamic module's methods to add selections -dynamically:

    -
    const { ref } = db.dynamic

    // Some column name provided by the user. Value not known at compile time.
    const columnFromUserInput = req.query.select;

    // A type that lists all possible values `columnFromUserInput` can have.
    // You can use `keyof Person` if any column of an interface is allowed.
    type PossibleColumns = 'last_name' | 'first_name' | 'birth_date'

    const spersons = await db
    .selectFrom('person')
    .select([
    ref<PossibleColumns>(columnFromUserInput)
    'id'
    ])
    .execute()

    // The resulting type contains all `PossibleColumns` as optional fields
    // because we cannot know which field was actually selected before
    // running the code.
    const lastName: string | undefined = persons[0].last_name
    const firstName: string | undefined = persons[0].first_name
    const birthDate: string | undefined = persons[0].birth_date

    // The result type also contains the compile time selection `id`.
    persons[0].id -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      SE extends string | AliasedExpression<any, any> | DynamicReferenceBuilder<any> | AliasedExpressionFactory<DB, TB>

    -
    -

    Parameters

    -
    -

    Returns SelectQueryBuilder<DB, TB, O & Selection<DB, TB, SE>>

-
- -
    - -
  • -

    Adds a select * or select table.* clause to the query.

    - - -

    Examples

    -
    -
    const persons = await db
    .selectFrom('person')
    .selectAll()
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "person"
    -
    -

    Select all columns of a table:

    -
    const persons = await db
    .selectFrom('person')
    .selectAll('person')
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select "person".* from "person"
    -
    -

    Select all columns of multiple tables:

    -
    const personsPets = await db
    .selectFrom(['person', 'pet'])
    .selectAll(['person', 'pet'])
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select "person".*, "pet".* from "person", "pet"
    -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T extends string | number | symbol

    -
    -

    Parameters

    -
      -
    • -
      table: readonly T[]
    -

    Returns SelectQueryBuilder<DB, TB, O & AllSelection<DB, T>>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      T extends string | number | symbol

    -
    -

    Parameters

    -
      -
    • -
      table: T
    -

    Returns SelectQueryBuilder<DB, TB, Selectable<DB[T]>>

  • - -
  • -

    Returns SelectQueryBuilder<DB, TB, O & AllSelection<DB, TB>>

-
- -
-
- -
    - -
  • -

    Executes the query and streams the rows.

    -

    The optional argument chunkSize defines how many rows to fetch from the database -at a time. It only affects some dialects like PostgreSQL that support it.

    - - -

    Examples

    -
    -
    const stream = db.
    .selectFrom('person')
    .select(['first_name', 'last_name'])
    .where('gender', '=', 'other')
    .stream()

    for await (const person of stream) {
    console.log(person.first_name)

    if (person.last_name === 'Something') {
    // Breaking or returning before the stream has ended will release
    // the database connection and invalidate the stream.
    break
    }
    } -
    -
    -
    -

    Parameters

    -
      -
    • -
      chunkSize: number = 100
    -

    Returns AsyncIterableIterator<O>

-
- -
    - -
  • -

    Creates the OperationNode that describes how to compile this expression into SQL.

    -

    If you are creating a custom expression, it's often easiest to use the sql -template tag to build the node:

    -
    class SomeExpression<T> implements Expression<T> {
    toOperationNode(): OperationNode {
    return sql`some sql here`.toOperationNode()
    }
    } -
    -
    -

    Returns SelectQueryNode

-
- -
-
- -
-
- -
    - -
  • -

    Adds a where expression to the query.

    -

    Calling this method multiple times will combine the expressions using and.

    -

    Also see whereRef

    - - -

    Examples

    -
    -
    const person = await db
    .selectFrom('person')
    .selectAll()
    .where('first_name', '=', 'Jennifer')
    .where('age', '>', 40)
    .executeTakeFirst() -
    -

    The generated SQL (PostgreSQL):

    -
    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:

    -
    sql`your operator`
    -
    -

    You can add expressions conditionally like this:

    -
    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)
    }

    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 ExpressionBuilder passed to the callback:

    -
    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):

    -
    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:

    -
    const persons = await db
    .selectFrom('person')
    .selectAll()
    .where('person.id', 'in', [100, 200, 300])
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "person" where "id" in ($1, $2, $3)
    -
    -

    For complex where expressions you can pass in a single callback and -use the ExpressionBuilder to build your expression:

    -
    const persons = await db
    .selectFrom('person')
    .selectAll('person')
    .where(({ cmpr, or, and, not, exists, selectFrom, val }) => and([
    or([
    cmpr('first_name', '=', firstName),
    cmpr('age', '<', maxAge)
    ]),
    not(exists(
    selectFrom('pet').select('pet.id').whereRef('pet.owner_id', '=', 'person.id')
    ))
    ])) -
    -

    The generated SQL (PostgreSQL):

    -
    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 sql tag -as any of the arguments, including the operator:

    -
    importsql } from 'kysely'

    const persons = await db
    .selectFrom('person')
    .selectAll()
    .where(
    sql`coalesce(first_name, last_name)`,
    'like',
    '%' + name + '%',
    )
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    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 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 sql tag or db.dynamic. The example below -uses both:

    -
    importsql } from 'kysely'
    const { ref } = db.dynamic

    const persons = await db
    .selectFrom('person')
    .selectAll()
    .where(ref(columnFromUserInput), '=', 1)
    .where(sql.id(columnFromUserInput), '=', 2)
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      RE extends string | Expression<any> | DynamicReferenceBuilder<any> | SelectQueryBuilder<any, any, {}> | SelectQueryBuilderFactory<DB, TB, {}> | ExpressionFactory<DB, TB, any>

    -
    -

    Parameters

    -
    -

    Returns SelectQueryBuilder<DB, TB, O>

  • - -
  • -
    -

    Parameters

    -
    -

    Returns SelectQueryBuilder<DB, TB, O>

  • - -
  • -
    -

    Parameters

    -
    -

    Returns SelectQueryBuilder<DB, TB, O>

-
- -
-
- -
-
- -
    - -
  • -

    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:

    -
    db.selectFrom(['person', 'pet'])
    .selectAll()
    .whereRef('person.first_name', '=', 'pet.name') -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "person", "pet" where "person"."first_name" = "pet"."name"
    -
    -

    Usage in a subquery:

    -
    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"

    -
    -
    -

    Parameters

    -
    -

    Returns SelectQueryBuilder<DB, TB, O>

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/SingleConnectionProvider.html b/docs/classes/SingleConnectionProvider.html deleted file mode 100644 index a99785138..000000000 --- a/docs/classes/SingleConnectionProvider.html +++ /dev/null @@ -1,119 +0,0 @@ -SingleConnectionProvider | kysely
-
- -
-
-
-
- -

Class SingleConnectionProvider

-
-

Hierarchy

-
    -
  • SingleConnectionProvider
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/SqliteAdapter.html b/docs/classes/SqliteAdapter.html deleted file mode 100644 index c88ad1b20..000000000 --- a/docs/classes/SqliteAdapter.html +++ /dev/null @@ -1,165 +0,0 @@ -SqliteAdapter | kysely
-
- -
-
-
-
- -

Class SqliteAdapter

-
-

A basic implementation of DialectAdapter with sensible default values. -3rd party dialects can extend this instead of implementing the DialectAdapter -interface from scratch. That way all new settings will get default values when -they are added and there will be less breaking changes.

-
-
-

Hierarchy

-
    -
  • SqliteAdapter
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
    -
  • get supportsReturning(): boolean
  • -
  • -

    Whether or not this dialect supports the returning in inserts -updates and deletes.

    -
    -

    Returns boolean

-
- -
    -
  • get supportsTransactionalDdl(): boolean
  • -
  • -

    Whether or not this dialect supports transactional DDL.

    -

    If this is true, migrations are executed inside a transaction.

    -
    -

    Returns boolean

-
-

Methods

-
- -
    - -
  • -

    This method is used to acquire a lock for the migrations so that -it's not possible for two migration operations to run in parallel.

    -

    Most dialects have explicit locks that can be used, like advisory locks -in PostgreSQL and the get_lock function in MySQL.

    -

    If the dialect doesn't have explicit locks the lockTable -created by Kysely can be used instead. You can access it through the options object. -The lock table has two columns id and is_locked and there's only one row in the table -whose id is lockRowId. is_locked is an integer. Kysely -takes care of creating the lock table and inserting the one single row to it before this -method is executed. If the dialect supports schemas and the user has specified a custom -schema in their migration settings, the options object also contains the schema name in -lockTableSchema.

    -

    Here's an example of how you might implement this method for a dialect that doesn't -have explicit locks but supports FOR UPDATE row locks and transactional DDL:

    -
    {
    async acquireMigrationLock(db, options): Promise<void> {
    const queryDb = options.lockTableSchema
    ? db.withSchema(options.lockTableSchema)
    : db

    // Since our imaginary dialect supports transactional DDL and has
    // row locks, we can simply take a row lock here and it will guarantee
    // all subsequent calls to this method from other transactions will
    // wait until this transaction finishes.
    await queryDb
    .selectFrom(options.lockTable)
    .selectAll()
    .where('id', '=', options.lockRowId)
    .forUpdate()
    .execute()
    }
    } -
    -

    If supportsTransactionalDdl is true then the db passed to this method -is a transaction inside which the migrations will be executed. Otherwise -db is a single connection (session) that will be used to execute the -migrations.

    -
    -

    Returns Promise<void>

-
- -
    - -
  • -

    Releases the migration lock. See acquireMigrationLock.

    -

    If supportsTransactionalDdl is true then the db passed to this method -is a transaction inside which the migrations were executed. Otherwise db -is a single connection (session) that was used to execute the migrations -and the acquireMigrationLock call.

    -
    -

    Returns Promise<void>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/SqliteDialect.html b/docs/classes/SqliteDialect.html deleted file mode 100644 index 0c4f099ad..000000000 --- a/docs/classes/SqliteDialect.html +++ /dev/null @@ -1,154 +0,0 @@ -SqliteDialect | kysely
-
- -
-
-
-
- -

Class SqliteDialect

-
-

SQLite dialect that uses the better-sqlite3 library.

-

The constructor takes an instance of SqliteDialectConfig.

-
import Database from 'better-sqlite3'

new SqliteDialect({
database: new Database('db.sqlite')
}) -
-

If you want the pool to only be created once it's first used, database -can be a function:

-
import Database from 'better-sqlite3'

new SqliteDialect({
database: async () => new Database('db.sqlite')
}) -
-
-
-

Hierarchy

-
    -
  • SqliteDialect
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/SqliteDriver.html b/docs/classes/SqliteDriver.html deleted file mode 100644 index 24fa2b6b2..000000000 --- a/docs/classes/SqliteDriver.html +++ /dev/null @@ -1,196 +0,0 @@ -SqliteDriver | kysely
-
- -
-
-
-
- -

Class SqliteDriver

-
-

A Driver creates and releases database connections -and is also responsible for connection pooling (if the dialect supports pooling).

-
-
-

Hierarchy

-
    -
  • SqliteDriver
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Initializes the driver.

    -

    After calling this method the driver should be usable and acquireConnection etc. -methods should be callable.

    -
    -

    Returns Promise<void>

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/SqliteIntrospector.html b/docs/classes/SqliteIntrospector.html deleted file mode 100644 index aafb16eb7..000000000 --- a/docs/classes/SqliteIntrospector.html +++ /dev/null @@ -1,138 +0,0 @@ -SqliteIntrospector | kysely
-
- -
-
-
-
- -

Class SqliteIntrospector

-
-

An interface for getting the database metadata (names of the tables and columns etc.)

-
-
-

Hierarchy

-
    -
  • SqliteIntrospector
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/SqliteQueryCompiler.html b/docs/classes/SqliteQueryCompiler.html deleted file mode 100644 index a7b424b5b..000000000 --- a/docs/classes/SqliteQueryCompiler.html +++ /dev/null @@ -1,1692 +0,0 @@ -SqliteQueryCompiler | kysely
-
- -
-
-
-
- -

Class SqliteQueryCompiler

-
-

a QueryCompiler compiles a query expressed as a tree of OperationNodes into SQL.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
-
-

Properties

-
-
-

Accessors

-
-
-

Methods

-
addParameter -append -appendImmediateValue -appendValue -compileDistinctOn -compileList -compileQuery -compileUnwrappedIdentifier -getAutoIncrement -getCurrentParameterPlaceholder -getExplainOptionAssignment -getExplainOptionsDelimiter -getLeftExplainOptionsWrapper -getLeftIdentifierWrapper -getRightExplainOptionsWrapper -getRightIdentifierWrapper -getSql -isMinusOperator -sanitizeIdentifier -visitAddColumn -visitAddConstraint -visitAggregateFunction -visitAlias -visitAlterColumn -visitAlterTable -visitAnd -visitBinaryOperation -visitCase -visitCheckConstraint -visitColumn -visitColumnDefinition -visitColumnUpdate -visitCommonTableExpression -visitCommonTableExpressionName -visitCreateIndex -visitCreateSchema -visitCreateTable -visitCreateType -visitCreateView -visitDataType -visitDefaultInsertValue -visitDefaultValue -visitDeleteQuery -visitDropColumn -visitDropConstraint -visitDropIndex -visitDropSchema -visitDropTable -visitDropType -visitDropView -visitExplain -visitForeignKeyConstraint -visitFrom -visitFunction -visitGenerated -visitGroupBy -visitGroupByItem -visitHaving -visitIdentifier -visitInsertQuery -visitJoin -visitLimit -visitList -visitModifyColumn -visitNode -visitOffset -visitOn -visitOnConflict -visitOnDuplicateKey -visitOperator -visitOr -visitOrderBy -visitOrderByItem -visitOver -visitParens -visitPartitionBy -visitPartitionByItem -visitPrimaryKeyConstraint -visitPrimitiveValueList -visitRaw -visitReference -visitReferences -visitRenameColumn -visitReturning -visitSchemableIdentifier -visitSelectAll -visitSelectModifier -visitSelectQuery -visitSelection -visitSetOperation -visitTable -visitUnaryOperation -visitUniqueConstraint -visitUpdateQuery -visitUsing -visitValue -visitValueList -visitValues -visitWhen -visitWhere -visitWith -
-
-

Constructors

-
- -
-
-

Properties

-
- -
nodeStack: OperationNode[] = []
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/Transaction.html b/docs/classes/Transaction.html deleted file mode 100644 index d4367428c..000000000 --- a/docs/classes/Transaction.html +++ /dev/null @@ -1,805 +0,0 @@ -Transaction | kysely
-
- -
-
-
-
- -

Class Transaction<DB>

-
-

The main Kysely class.

-

You should create one instance of Kysely per database using the Kysely -constructor. Each Kysely instance maintains it's own connection pool.

- - -

Examples

-
-

This example assumes your database has tables person and pet:

-
importKysely, Generated, PostgresDialect } from 'kysely'

interface PersonTable {
id: Generated<number>
first_name: string
last_name: string
}

interface PetTable {
id: Generated<number>
owner_id: number
name: string
species 'cat' | 'dog'
}

interface Database {
person: PersonTable,
pet: PetTable
}

const db = new Kysely<Database>({
dialect: new PostgresDialect({
host: 'localhost',
database: 'kysely_test',
})
}) -
-
-
-

Type Parameters

-
    -
  • -

    DB

    -

    The database interface type. Keys of this type must be table names - in the database and values must be interfaces that describe the rows in those - tables. See the examples above.

    -
-
-

Hierarchy

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
- -
    -
  • get fn(): FunctionModule<DB, keyof DB>
  • -
  • -

    Returns a FunctionModule that can be used to write type safe function -calls.

    -
    const { count } = db.fn

    await db.selectFrom('person')
    .innerJoin('pet', 'pet.owner_id', 'person.id')
    .select([
    'person.id',
    count('pet.id').as('pet_count')
    ])
    .groupBy('person.id')
    .having(count('pet.id'), '>', 10)
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    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 -
    -
    -

    Returns FunctionModule<DB, keyof DB>

-
- -
-
- -
    -
  • get isTransaction(): true
  • -
  • -

    Returns true if this Kysely instance is a transaction.

    -

    You can also use db instanceof Transaction.

    -
    -

    Returns true

-
- -
-
-

Methods

-
- -
-
- -
    - -
  • -

    Provides a kysely instance bound to a single database connection.

    - - -

    Examples

    -
    -
    await db
    .connection()
    .execute(async (db) => {
    // `db` is an instance of `Kysely` that's bound to a single
    // database connection. All queries executed through `db` use
    // the same connection.
    await doStuff(db)
    }) -
    -
    -

    Returns ConnectionBuilder<DB>

-
- -
    - -
  • -

    Creates a delete query.

    -

    See the where method for examples on how to specify -a where clause for the delete operation.

    -

    The return value of the query is an instance of DeleteResult.

    - - -

    Examples

    -
    -

    Deleting person with id 1:

    -
    const result = await db
    .deleteFrom('person')
    .where('person.id', '=', 1)
    .executeTakeFirst()

    console.log(result.numDeletedRows) -
    -

    The generated SQL (PostgreSQL):

    -
    delete from "person" where "person"."id" = $1
    -
    -

    Some databases such as MySQL support deleting from multiple tables:

    -
    const result = await db
    .deleteFrom(['person', 'pet'])
    .using('person')
    .innerJoin('pet', 'pet.owner_id', '=', 'person.id')
    .where('person.id', '=', 1)
    .executeTakeFirst() -
    -

    The generated SQL (MySQL):

    -
    delete from `person`, `pet`
    using `person`
    inner join `pet` on `pet`.`owner_id` = `person`.`id`
    where `person`.`id` = ? -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TR extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TR[]
    -

    Returns DeleteQueryBuilder<DB, ExtractTableAlias<DB, TR>, DeleteResult>

  • - -
  • -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      tables: TR[]
    -

    Returns DeleteQueryBuilder<DrainOuterGeneric<{ [ C in any]: C extends ExtractAliasFromTableExpression<DB, TR> ? ExtractRowTypeFromTableExpression<DB, TR, C> : C extends keyof DB ? DB[C] : never }>, DrainOuterGeneric<ExtractAliasFromTableExpression<DB, TR>>, DeleteResult>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TR extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TR
    -

    Returns DeleteQueryBuilder<DB, ExtractTableAlias<DB, TR>, DeleteResult>

  • - -
  • -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      table: TR
    -

    Returns DeleteQueryBuilder<DrainOuterGeneric<{ [ C in any]: C extends ExtractAliasFromTableExpression<DB, TR> ? ExtractRowTypeFromTableExpression<DB, TR, C> : C extends keyof DB ? DB[C] : never }>, DrainOuterGeneric<ExtractAliasFromTableExpression<DB, TR>>, DeleteResult>

-
- -
    - -
  • -

    Releases all resources and disconnects from the database.

    -

    You need to call this when you are done using the Kysely instance.

    -
    -

    Returns Promise<void>

-
- -
-
- -
    - -
  • -

    Creates an insert query.

    -

    The return value of this query is an instance of InsertResult. InsertResult -has the insertId field that holds the auto incremented id of -the inserted row if the db returned one.

    -

    See the values method for more info and examples. Also see -the returning method for a way to return columns -on supported databases like PostgreSQL.

    - - -

    Examples

    -
    -
    const result = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .executeTakeFirst()

    console.log(result.insertId) -
    -

    Some databases like PostgreSQL support the returning method:

    -
    const { id } = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .returning('id')
    .executeTakeFirst() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T extends string

    -
    -

    Parameters

    -
      -
    • -
      table: T
    -

    Returns InsertQueryBuilder<DB, T, InsertResult>

-
- -
-
- -
    - -
  • -

    Creates a select query builder for the given table or tables.

    -

    The tables passed to this method are built as the query's from clause.

    - - -

    Examples

    -
    -

    Create a select query for one table:

    -
    db.selectFrom('person').selectAll()
    -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "person"
    -
    -

    Create a select query for one table with an alias:

    -
    const persons = await db.selectFrom('person as p')
    .select(['p.id', 'first_name'])
    .execute()

    console.log(persons[0].id) -
    -

    The generated SQL (PostgreSQL):

    -
    select "p"."id", "first_name" from "person" as "p"
    -
    -

    Create a select query from a subquery:

    -
    const persons = await db.selectFrom(
    (eb) => eb.selectFrom('person').select('person.id as identifier').as('p')
    )
    .select('p.identifier')
    .execute()

    console.log(persons[0].identifier) -
    -

    The generated SQL (PostgreSQL):

    -
    select "p"."identifier",
    from (
    select "person"."id" as "identifier" from "person"
    ) as p -
    -

    Create a select query from raw sql:

    -
    importsql } from 'kysely'

    const items = await db
    .selectFrom(sql<{ one: number }>`(select 1 as one)`.as('q'))
    .select('q.one')
    .execute()

    console.log(items[0].one) -
    -

    The generated SQL (PostgreSQL):

    -
    select "q"."one",
    from (
    select 1 as one
    ) as q -
    -

    When you use the sql tag you need to also provide the result type of the -raw snippet / query so that Kysely can figure out what columns are -available for the rest of the query.

    -

    The selectFrom method also accepts an array for multiple tables. All -the above examples can also be used in an array.

    -
    importsql } from 'kysely'

    const items = await db.selectFrom([
    'person as p',
    db.selectFrom('pet').select('pet.species').as('a'),
    sql<{ one: number }>`(select 1 as one)`.as('q')
    ])
    .select(['p.id', 'a.species', 'q.one'])
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select "p".id, "a"."species", "q"."one"
    from
    "person" as "p",
    (select "pet"."species" from "pet") as a,
    (select 1 as one) as "q" -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TE extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TE[]
    -

    Returns SelectQueryBuilder<DB, ExtractTableAlias<DB, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, keyof DB>

    -
    -

    Parameters

    -
      -
    • -
      from: TE[]
    -

    Returns SelectQueryBuilder<DrainOuterGeneric<{ [ C in any]: C extends ExtractAliasFromTableExpression<DB, TE> ? ExtractRowTypeFromTableExpression<DB, TE, C> : C extends keyof DB ? DB[C] : never }>, DrainOuterGeneric<ExtractAliasFromTableExpression<DB, TE>>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TE
    -

    Returns SelectQueryBuilder<DB, ExtractTableAlias<DB, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends `${string} as ${string}`

    -
    -

    Parameters

    -
      -
    • -
      from: TE
    -

    Returns SelectQueryBuilder<DB & PickTableWithAlias<DB, TE>, ExtractTableAlias<DB, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, keyof DB>

    -
    -

    Parameters

    -
      -
    • -
      from: TE
    -

    Returns SelectQueryBuilder<DrainOuterGeneric<{ [ C in any]: C extends ExtractAliasFromTableExpression<DB, TE> ? ExtractRowTypeFromTableExpression<DB, TE, C> : C extends keyof DB ? DB[C] : never }>, DrainOuterGeneric<ExtractAliasFromTableExpression<DB, TE>>, {}>

-
- -
    - -
  • -

    Creates a TransactionBuilder that can be used to run queries inside a transaction.

    -

    The returned TransactionBuilder can be used to configure the transaction. The -execute method can then be called to run the transaction. -execute takes a function that is run inside the -transaction. If the function throws, the transaction is rolled back. Otherwise -the transaction is committed.

    -

    The callback function passed to the execute -method gets the transaction object as its only argument. The transaction is -of type Transaction which inherits Kysely. Any query -started through the transaction object is executed inside the transaction.

    - - -

    Examples

    -
    -
    const catto = await db.transaction().execute(async (trx) => {
    const jennifer = await trx.insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston',
    })
    .returning('id')
    .executeTakeFirstOrThrow()

    await someFunction(trx, jennifer)

    return await trx.insertInto('pet')
    .values({
    user_id: jennifer.id,
    name: 'Catto',
    species: 'cat'
    })
    .returningAll()
    .executeTakeFirst()
    }) -
    -

    Setting the isolation level:

    -
    await db
    .transaction()
    .setIsolationLevel('serializable')
    .execute(async (trx) => {
    await doStuff(trx)
    }) -
    -
    -

    Returns TransactionBuilder<DB>

-
- -
    - -
  • -

    Creates an update query.

    -

    See the where method for examples on how to specify -a where clause for the update operation.

    -

    See the set method for examples on how to -specify the updates.

    -

    The return value of the query is an UpdateResult.

    - - -

    Examples

    -
    -
    const result = await db
    .updateTable('person')
    .set({ first_name: 'Jennifer' })
    .where('person.id', '=', 1)
    .executeTakeFirst()

    console.log(result.numUpdatedRows) -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TR extends string

    -
    -

    Parameters

    -
      -
    • -
      table: TR
    -

    Returns UpdateQueryBuilder<DB, ExtractTableAlias<DB, TR>, ExtractTableAlias<DB, TR>, UpdateResult>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TR extends `${string} as ${string}`

    -
    -

    Parameters

    -
      -
    • -
      table: TR
    -

    Returns UpdateQueryBuilder<DB & PickTableWithAlias<DB, TR>, ExtractTableAlias<DB, TR>, ExtractTableAlias<DB, TR>, UpdateResult>

  • - -
  • -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      table: TR
    -

    Returns UpdateQueryBuilder<DrainOuterGeneric<{ [ C in any]: C extends ExtractAliasFromTableExpression<DB, TR> ? ExtractRowTypeFromTableExpression<DB, TR, C> : C extends keyof DB ? DB[C] : never }>, DrainOuterGeneric<ExtractAliasFromTableExpression<DB, TR>>, DrainOuterGeneric<ExtractAliasFromTableExpression<DB, TR>>, UpdateResult>

-
- -
    - -
  • -

    Creates a with query (Common Table Expression).

    - - -

    Examples

    -
    -
    await db
    .with('jennifers', (db) => db
    .selectFrom('person')
    .where('first_name', '=', 'Jennifer')
    .select(['id', 'age'])
    )
    .with('adult_jennifers', (db) => db
    .selectFrom('jennifers')
    .where('age', '>', 18)
    .select(['id', 'age'])
    )
    .selectFrom('adult_jennifers')
    .where('age', '<', 60)
    .selectAll()
    .execute() -
    -

    The CTE name can optionally specify column names in addition to -a name. In that case Kysely requires the expression to retun -rows with the same columns.

    -
    await db
    .with('jennifers(id, age)', (db) => db
    .selectFrom('person')
    .where('first_name', '=', 'Jennifer')
    // This is ok since we return columns with the same
    // names as specified by `jennifers(id, age)`.
    .select(['id', 'age'])
    )
    .selectFrom('jennifers')
    .selectAll()
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      N extends string

    • -
    • -

      E extends CommonTableExpression<DB, N>

    -
    -

    Parameters

    -
      -
    • -
      name: N
    • -
    • -
      expression: E
    -

    Returns QueryCreatorWithCommonTableExpression<DB, N, E>

-
- -
-
- -
    - -
  • -

    Creates a recursive with query (Common Table Expression).

    -

    See the with method for examples and more documentation.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      N extends string

    • -
    • -

      E extends RecursiveCommonTableExpression<DB, N>

    -
    -

    Parameters

    -
      -
    • -
      name: N
    • -
    • -
      expression: E
    -

    Returns QueryCreatorWithCommonTableExpression<DB, N, E>

-
- -
-
- -
    - -
  • -

    Returns a copy of this Kysely instance with tables added to its -database type.

    -

    This method only modifies the types and doesn't affect any of the -executed queries in any way.

    - - -

    Examples

    -
    -

    The following example adds and uses a temporary table:

    - -

    Example

    await db.schema
    .createTable('temp_table')
    .temporary()
    .addColumn('some_column', 'integer')
    .execute()

    const tempDb = db.withTables<{
    temp_table: {
    some_column: number
    }
    }>()

    await tempDb
    .insertInto('temp_table')
    .values({ some_column: 100 })
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T extends Record<string, Record<string, any>>

    -

    Returns Transaction<DB & T>

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/TransactionBuilder.html b/docs/classes/TransactionBuilder.html deleted file mode 100644 index 202c91baf..000000000 --- a/docs/classes/TransactionBuilder.html +++ /dev/null @@ -1,136 +0,0 @@ -TransactionBuilder | kysely
-
- -
-
-
-
- -

Class TransactionBuilder<DB>

-
-

Type Parameters

-
    -
  • -

    DB

-
-

Hierarchy

-
    -
  • TransactionBuilder
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -
    -

    Type Parameters

    -
      -
    • -

      T

    -
    -

    Parameters

    -
    -

    Returns Promise<T>

-
- -
    - -
  • -
    -

    Parameters

    -
      -
    • -
      isolationLevel: "read uncommitted" | "read committed" | "repeatable read" | "serializable"
    -

    Returns TransactionBuilder<DB>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/UpdateQueryBuilder.html b/docs/classes/UpdateQueryBuilder.html deleted file mode 100644 index 13ad7de0a..000000000 --- a/docs/classes/UpdateQueryBuilder.html +++ /dev/null @@ -1,1274 +0,0 @@ -UpdateQueryBuilder | kysely
-
- -
-
-
-
- -

Class UpdateQueryBuilder<DB, UT, TB, O>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    UT extends keyof DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    O

-
-

Hierarchy

-
    -
  • UpdateQueryBuilder
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    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

    -
    -
    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() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -

    Returns O extends T ? UpdateQueryBuilder<DB, UT, TB, T> : KyselyTypeError<"$assertType() call failed: The type passed in is not equal to the output type of the query.">

-
- -
    - -
  • -

    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 $if method.

    - - -

    Examples

    -
    -

    The next example uses a helper function log to log a query:

    -
    function log<T extends Compilable>(qb: T): T {
    console.log(qb.compile())
    return qb
    }

    db.updateTable('person')
    .set(values)
    .$call(log)
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -
    -

    Parameters

    -
    -

    Returns T

-
- -
-
- -
    - -
  • -

    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

    -
    -
    async function updatePerson(id: number, updates: UpdateablePerson, 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:

    -
    {
    id: number
    first_name: string
    last_name?: string
    } -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      O2

    -
    -

    Parameters

    -
    -

    Returns O2 extends UpdateResult ? UpdateQueryBuilder<DB, UT, TB, UpdateResult> : O2 extends O & E ? UpdateQueryBuilder<DB, UT, TB, O & Partial<E>> : UpdateQueryBuilder<DB, UT, TB, Partial<O2>>

-
- -
    - -
  • -

    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 set input -when using where and/or returning or 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:

    -
    const person = await db.updateTable('person')
    .set({ deletedAt: now })
    .where('id', '=', id)
    .where('nullable_column', 'is not', null)
    .returningAll()
    .executeTakeFirstOrThrow()

    if (person.nullable_column) {
    functionThatExpectsPersonWithNonNullValue(person)
    } -
    -

    Into this:

    -
    const person = await db.updateTable('person')
    .set({ deletedAt: now })
    .where('id', '=', id)
    .where('nullable_column', 'is not', null)
    .returningAll()
    .$narrowType<{ deletedAt: Date; nullable_column: string }>()
    .executeTakeFirstOrThrow()

    functionThatExpectsPersonWithNonNullValue(person) -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -

    Returns UpdateQueryBuilder<DB, UT, TB, NarrowPartial<O, T>>

-
- -
    - -
  • -
    -

    Deprecated

    Use $assertType instead.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -

    Returns O extends T ? UpdateQueryBuilder<DB, UT, TB, T> : KyselyTypeError<"assertType() call failed: The type passed in is not equal to the output type of the query.">

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Executes the query and returns the first result or undefined if -the query returned no result.

    -
    -

    Returns Promise<SimplifySingleResult<O>>

-
- -
    - -
  • -

    Executes the query and returns the first result or throws if -the query returned no result.

    -

    By default an instance of NoResultError is thrown, but you can -provide a custom error class, or callback as the only argument to throw a different -error.

    -
    -
    -

    Parameters

    -
    -

    Returns Promise<SimplifyResult<O>>

-
- -
    - -
  • -

    Executes query with explain statement before the main query.

    -
    const explained = await db
    .selectFrom('person')
    .where('gender', '=', 'female')
    .selectAll()
    .explain('json') -
    -

    The generated SQL (MySQL):

    -
    explain format=json select * from `person` where `gender` = ?
    -
    -

    You can also execute explain analyze statements.

    -
    import { sql } from 'kysely'

    const explained = await db
    .selectFrom('person')
    .where('gender', '=', 'female')
    .selectAll()
    .explain('json', sql`analyze`) -
    -

    The generated SQL (PostgreSQL):

    -
    explain (analyze, format json) select * from "person" where "gender" = $1
    -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      ER extends Record<string, any> = Record<string, any>

    -
    -

    Parameters

    -
    -

    Returns Promise<ER[]>

-
- -
    - -
  • -

    Adds a from clause to the update query.

    -

    This is supported only on some databases like PostgreSQL.

    -

    The API is the same as selectFrom.

    - - -

    Examples

    -
    -
    db.updateTable('person')
    .from('pet')
    .set((eb) => ({
    first_name: eb.ref('pet.name')
    }))
    .whereRef('pet.owner_id', '=', 'person.id') -
    -

    The generated SQL (PostgreSQL):

    -
    update "person"
    set "first_name" = "pet"."name"
    from "pet"
    where "pet"."owner_id" = "person"."id" -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, TB>

    -
    -

    Parameters

    -
      -
    • -
      table: TE
    -

    Returns UpdateQueryBuilder<From<DB, TE>, UT, FromTables<DB, TB, TE>, O>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, TB>

    -
    -

    Parameters

    -
      -
    • -
      table: TE[]
    -

    Returns UpdateQueryBuilder<From<DB, TE>, UT, FromTables<DB, TB, TE>, O>

-
- -
-
- -
-
- -
    - -
  • -

    Joins another table to the query using an inner join.

    - - -

    Examples

    -
    -

    Simple usage by providing a table name and two columns to join:

    -
    const result = await db
    .selectFrom('person')
    .innerJoin('pet', 'pet.owner_id', 'person.id')
    // `select` needs to come after the call to `innerJoin` so
    // that you can select from the joined table.
    .select(['person.id', 'pet.name'])
    .execute()

    result[0].id
    result[0].name -
    -

    The generated SQL (PostgreSQL):

    -
    select "person"."id", "pet"."name"
    from "person"
    inner join "pet"
    on "pet"."owner_id" = "person"."id" -
    -

    You can give an alias for the joined table like this:

    -
    await db.selectFrom('person')
    .innerJoin('pet as p', 'p.owner_id', 'person.id')
    .where('p.name', '=', 'Doggo')
    .selectAll()
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select *
    from "person"
    inner join "pet" as "p"
    on "p"."owner_id" = "person"."id"
    where "p".name" = $1 -
    -

    You can provide a function as the second argument to get a join -builder for creating more complex joins. The join builder has a -bunch of on* methods for building the on clause of the join. -There's basically an equivalent for every where method -(on, onRef, onExists etc.). You can do all the same things -with the on method that you can with the corresponding where -method. See the where method documentation for more examples.

    -
    await db.selectFrom('person')
    .innerJoin(
    'pet',
    (join) => join
    .onRef('pet.owner_id', '=', 'person.id')
    .on('pet.name', '=', 'Doggo')
    )
    .selectAll()
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select *
    from "person"
    inner join "pet"
    on "pet"."owner_id" = "person"."id"
    and "pet"."name" = $1 -
    -

    You can join a subquery by providing a select query (or a callback) -as the first argument:

    -
    await db.selectFrom('person')
    .innerJoin(
    qb.selectFrom('pet')
    .select(['owner_id', 'name'])
    .where('name', '=', 'Doggo')
    .as('doggos'),
    'doggos.owner_id',
    'person.id',
    )
    .selectAll()
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select *
    from "person"
    inner join (
    select "owner_id", "name"
    from "pet"
    where "name" = $1
    ) as "doggos"
    on "doggos"."owner_id" = "person"."id" -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, TB>

    • -
    • -

      K1 extends string

    • -
    • -

      K2 extends string

    -
    -

    Parameters

    -
      -
    • -
      table: TE
    • -
    • -
      k1: K1
    • -
    • -
      k2: K2
    -

    Returns UpdateQueryBuilderWithInnerJoin<DB, UT, TB, O, TE>

  • - -
  • -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      table: TE
    • -
    • -
      callback: FN
    -

    Returns UpdateQueryBuilderWithInnerJoin<DB, UT, TB, O, TE>

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Allows you to return data from modified rows.

    -

    On supported databases like PostgreSQL, this method can be chained to -insert, update and delete queries to return data.

    -

    Note that on SQLite you need to give aliases for the expressions to avoid -this bug in SQLite. -For example .returning('id as id').

    -

    Also see the returningAll method.

    - - -

    Examples

    -
    -

    Return one column:

    -
    const { id } = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .returning('id')
    .executeTakeFirst() -
    -

    Return multiple columns:

    -
    const { id, first_name } = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .returning(['id', 'last_name'])
    .executeTakeFirst() -
    -

    Return arbitrary expressions:

    -
    importsql } 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('pets').select('pet.id').limit(1).as('first_pet_id')
    ])
    .executeTakeFirst() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      SE extends string | AliasedExpression<any, any> | DynamicReferenceBuilder<any> | AliasedExpressionFactory<DB, TB>

    -
    -

    Parameters

    -
    -

    Returns UpdateQueryBuilder<DB, UT, TB, ReturningRow<DB, TB, O, SE>>

-
- -
-
- -
-
- -
    - -
  • -

    Sets the values to update for an update query.

    -

    This method takes an object whose keys are column names and values are -values to update. In addition to the column's type, the values can be -any expressions such as raw sql snippets or select queries.

    -

    This method also accepts a callback that returns the update object. The -callback takes an instance of ExpressionBuilder as its only argument. -The expression builder can be used to create arbitrary update expressions.

    -

    The return value of an update query is an instance of UpdateResult. -You can use the returning method on supported databases to get out -the updated rows.

    - - -

    Examples

    -
    -

    Update a row in person table:

    -
    const result = await db
    .updateTable('person')
    .set({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .where('id', '=', 1)
    .executeTakeFirst()

    console.log(result.numUpdatedRows) -
    -

    The generated SQL (PostgreSQL):

    -
    update "person" set "first_name" = $1, "last_name" = $2 where "id" = $3
    -
    -

    On PostgreSQL you ca chain returning to the query to get -the updated rows' columns (or any other expression) as the -return value:

    -
    const row = await db
    .updateTable('person')
    .set({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .where('id', '=', 1)
    .returning('id')
    .executeTakeFirstOrThrow()

    row.id -
    -

    The generated SQL (PostgreSQL):

    -
    update "person" set "first_name" = $1, "last_name" = $2 where "id" = $3 returning "id"
    -
    -

    In addition to primitives, the values can arbitrary expressions including -raw sql snippets or subqueries:

    -
    import { sql } from 'kysely'

    const result = await db
    .updateTable('person')
    .set(({ selectFrom, ref, fn, bxp }) => ({
    first_name: selectFrom('person').select('first_name').limit(1),
    middle_name: ref('first_name'),
    age: bxp('age', '+', 1),
    last_name: sql`${'Ani'} || ${'ston'}`,
    }))
    .where('id', '=', 1)
    .executeTakeFirst()

    console.log(result.numUpdatedRows) -
    -

    The generated SQL (PostgreSQL):

    -
    update "person" set
    "first_name" = (select "first_name" from "person" limit $1),
    "middle_name" = "first_name",
    "age" = "age" + $2,
    "last_name" = $3 || $4
    where "id" = $5 -
    -
    -
    -

    Parameters

    -
    -

    Returns UpdateQueryBuilder<DB, UT, TB, O>

  • - -
  • -
    -

    Parameters

    -
      -
    • -
      update: UpdateObjectFactory<DB, TB, UT>
    -

    Returns UpdateQueryBuilder<DB, UT, TB, O>

-
- -
    - -
  • -

    Executes the query and streams the rows.

    -

    The optional argument chunkSize defines how many rows to fetch from the database -at a time. It only affects some dialects like PostgreSQL that support it.

    - - -

    Examples

    -
    -
    const stream = db.
    .selectFrom('person')
    .select(['first_name', 'last_name'])
    .where('gender', '=', 'other')
    .stream()

    for await (const person of stream) {
    console.log(person.first_name)

    if (person.last_name === 'Something') {
    // Breaking or returning before the stream has ended will release
    // the database connection and invalidate the stream.
    break
    }
    } -
    -
    -
    -

    Parameters

    -
      -
    • -
      chunkSize: number = 100
    -

    Returns AsyncIterableIterator<O>

-
- -
-
- -
    - -
  • -

    Adds a where expression to the query.

    -

    Calling this method multiple times will combine the expressions using and.

    -

    Also see whereRef

    - - -

    Examples

    -
    -
    const person = await db
    .selectFrom('person')
    .selectAll()
    .where('first_name', '=', 'Jennifer')
    .where('age', '>', 40)
    .executeTakeFirst() -
    -

    The generated SQL (PostgreSQL):

    -
    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:

    -
    sql`your operator`
    -
    -

    You can add expressions conditionally like this:

    -
    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)
    }

    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 ExpressionBuilder passed to the callback:

    -
    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):

    -
    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:

    -
    const persons = await db
    .selectFrom('person')
    .selectAll()
    .where('person.id', 'in', [100, 200, 300])
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "person" where "id" in ($1, $2, $3)
    -
    -

    For complex where expressions you can pass in a single callback and -use the ExpressionBuilder to build your expression:

    -
    const persons = await db
    .selectFrom('person')
    .selectAll('person')
    .where(({ cmpr, or, and, not, exists, selectFrom, val }) => and([
    or([
    cmpr('first_name', '=', firstName),
    cmpr('age', '<', maxAge)
    ]),
    not(exists(
    selectFrom('pet').select('pet.id').whereRef('pet.owner_id', '=', 'person.id')
    ))
    ])) -
    -

    The generated SQL (PostgreSQL):

    -
    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 sql tag -as any of the arguments, including the operator:

    -
    importsql } from 'kysely'

    const persons = await db
    .selectFrom('person')
    .selectAll()
    .where(
    sql`coalesce(first_name, last_name)`,
    'like',
    '%' + name + '%',
    )
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    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 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 sql tag or db.dynamic. The example below -uses both:

    -
    importsql } from 'kysely'
    const { ref } = db.dynamic

    const persons = await db
    .selectFrom('person')
    .selectAll()
    .where(ref(columnFromUserInput), '=', 1)
    .where(sql.id(columnFromUserInput), '=', 2)
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      RE extends string | Expression<any> | DynamicReferenceBuilder<any> | SelectQueryBuilder<any, any, {}> | SelectQueryBuilderFactory<DB, TB, {}> | ExpressionFactory<DB, TB, any>

    -
    -

    Parameters

    -
    -

    Returns UpdateQueryBuilder<DB, UT, TB, O>

  • - -
  • -
    -

    Parameters

    -
    -

    Returns UpdateQueryBuilder<DB, UT, TB, O>

  • - -
  • -
    -

    Parameters

    -
    -

    Returns UpdateQueryBuilder<DB, UT, TB, O>

-
- -
-
- -
-
- -
    - -
  • -

    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:

    -
    db.selectFrom(['person', 'pet'])
    .selectAll()
    .whereRef('person.first_name', '=', 'pet.name') -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "person", "pet" where "person"."first_name" = "pet"."name"
    -
    -

    Usage in a subquery:

    -
    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"

    -
    -
    -

    Parameters

    -
    -

    Returns UpdateQueryBuilder<DB, UT, TB, O>

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/UpdateResult.html b/docs/classes/UpdateResult.html deleted file mode 100644 index e23ddc1d2..000000000 --- a/docs/classes/UpdateResult.html +++ /dev/null @@ -1,90 +0,0 @@ -UpdateResult | kysely
-
- -
-
-
-
- -

Class UpdateResult

-
-

Hierarchy

-
    -
  • UpdateResult
-
-
-
- -
-
-

Constructors

-
-
-

Accessors

-
-
-

Constructors

-
- -
-
-

Accessors

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/WithSchemaPlugin.html b/docs/classes/WithSchemaPlugin.html deleted file mode 100644 index ba147a84c..000000000 --- a/docs/classes/WithSchemaPlugin.html +++ /dev/null @@ -1,132 +0,0 @@ -WithSchemaPlugin | kysely
-
- -
-
-
-
- -

Class WithSchemaPlugin

-
-

Hierarchy

-
    -
  • WithSchemaPlugin
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Methods

-
-
-

Constructors

-
- -
-
-

Methods

-
- -
    - -
  • -

    This is called for each query before it is executed. You can modify the query by -transforming its OperationNode tree provided in args.node -and returning the transformed tree. You'd usually want to use an OperationNodeTransformer -for this.

    -

    If you need to pass some query-related data between this method and transformResult you -can use a WeakMap with args.queryId as the key:

    -
    const plugin = {
    data: new WeakMap<QueryId, SomeData>(),

    transformQuery(args: PluginTransformQueryArgs): RootOperationNode {
    this.data.set(args.queryId, something)
    return args.node
    },

    transformResult(args: PluginTransformResultArgs): QueryResult<UnknownRow> {
    const data = this.data.get(args.queryId)
    return args.result
    }
    } -
    -

    You should use a WeakMap instead of a Map or some other strong references because transformQuery -is not always matched by a call to transformResult which would leave orphaned items in the map -and cause a memory leak.

    -
    -
    -

    Parameters

    -
    -

    Returns RootOperationNode

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/createFunctionModule.html b/docs/functions/createFunctionModule.html deleted file mode 100644 index c337cdf96..000000000 --- a/docs/functions/createFunctionModule.html +++ /dev/null @@ -1,442 +0,0 @@ -createFunctionModule | kysely
-
- -
-
-
-
- -

Function createFunctionModule

-
-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/expressionBuilder-1.html b/docs/functions/expressionBuilder-1.html deleted file mode 100644 index 6f6943084..000000000 --- a/docs/functions/expressionBuilder-1.html +++ /dev/null @@ -1,459 +0,0 @@ -expressionBuilder | kysely
-
- -
-
-
-
- -

Function expressionBuilder

-
-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/isAliasedExpression.html b/docs/functions/isAliasedExpression.html deleted file mode 100644 index 359b85ba1..000000000 --- a/docs/functions/isAliasedExpression.html +++ /dev/null @@ -1,440 +0,0 @@ -isAliasedExpression | kysely
-
- -
-
-
-
- -

Function isAliasedExpression

-
-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/isArithmeticOperator.html b/docs/functions/isArithmeticOperator.html deleted file mode 100644 index fa58cd0b7..000000000 --- a/docs/functions/isArithmeticOperator.html +++ /dev/null @@ -1,440 +0,0 @@ -isArithmeticOperator | kysely
-
- -
-
-
-
- -

Function isArithmeticOperator

-
-
    - -
  • -
    -

    Parameters

    -
      -
    • -
      op: unknown
    -

    Returns op is "+" | "-" | "*" | "/" | "%" | "^" | "&" | "|" | "#" | "<<" | ">>"

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/isBinaryOperator.html b/docs/functions/isBinaryOperator.html deleted file mode 100644 index 47f3c6955..000000000 --- a/docs/functions/isBinaryOperator.html +++ /dev/null @@ -1,440 +0,0 @@ -isBinaryOperator | kysely
-
- -
-
-
-
- -

Function isBinaryOperator

-
-
    - -
  • -
    -

    Parameters

    -
      -
    • -
      op: unknown
    -

    Returns op is "match" | "is" | "=" | "==" | "!=" | "<>" | ">" | ">=" | "<" | "<=" | "in" | "not in" | "is not" | "like" | "not like" | "ilike" | "not ilike" | "@>" | "<@" | "?" | "?&" | "!<" | "!>" | "<=>" | "!~" | "~" | "~*" | "!~*" | "@@" | "@@@" | "!!" | "<->" | "+" | "-" | "*" | "/" | "%" | "^" | "&" | "|" | "#" | "<<" | ">>" | "&&" | "||"

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/isComparisonOperator.html b/docs/functions/isComparisonOperator.html deleted file mode 100644 index 88e0b751d..000000000 --- a/docs/functions/isComparisonOperator.html +++ /dev/null @@ -1,440 +0,0 @@ -isComparisonOperator | kysely
-
- -
-
-
-
- -

Function isComparisonOperator

-
-
    - -
  • -
    -

    Parameters

    -
      -
    • -
      op: unknown
    -

    Returns op is "match" | "is" | "=" | "==" | "!=" | "<>" | ">" | ">=" | "<" | "<=" | "in" | "not in" | "is not" | "like" | "not like" | "ilike" | "not ilike" | "@>" | "<@" | "?" | "?&" | "!<" | "!>" | "<=>" | "!~" | "~" | "~*" | "!~*" | "@@" | "@@@" | "!!" | "<->"

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/isCompilable.html b/docs/functions/isCompilable.html deleted file mode 100644 index 392d21b88..000000000 --- a/docs/functions/isCompilable.html +++ /dev/null @@ -1,440 +0,0 @@ -isCompilable | kysely
-
- -
-
-
-
- -

Function isCompilable

-
-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/isExpression.html b/docs/functions/isExpression.html deleted file mode 100644 index 029a7d850..000000000 --- a/docs/functions/isExpression.html +++ /dev/null @@ -1,440 +0,0 @@ -isExpression | kysely
-
- -
-
-
-
- -

Function isExpression

-
-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/isKyselyProps.html b/docs/functions/isKyselyProps.html deleted file mode 100644 index 63acbe447..000000000 --- a/docs/functions/isKyselyProps.html +++ /dev/null @@ -1,440 +0,0 @@ -isKyselyProps | kysely
-
- -
-
-
-
- -

Function isKyselyProps

-
-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/isNoResultErrorConstructor.html b/docs/functions/isNoResultErrorConstructor.html deleted file mode 100644 index adcd748f7..000000000 --- a/docs/functions/isNoResultErrorConstructor.html +++ /dev/null @@ -1,440 +0,0 @@ -isNoResultErrorConstructor | kysely
-
- -
-
-
-
- -

Function isNoResultErrorConstructor

-
-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/isOperationNodeSource.html b/docs/functions/isOperationNodeSource.html deleted file mode 100644 index bf8c6443b..000000000 --- a/docs/functions/isOperationNodeSource.html +++ /dev/null @@ -1,440 +0,0 @@ -isOperationNodeSource | kysely
-
- -
-
-
-
- -

Function isOperationNodeSource

-
-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/isOperator.html b/docs/functions/isOperator.html deleted file mode 100644 index fd90ca999..000000000 --- a/docs/functions/isOperator.html +++ /dev/null @@ -1,440 +0,0 @@ -isOperator | kysely
-
- -
-
-
-
- -

Function isOperator

-
-
    - -
  • -
    -

    Parameters

    -
      -
    • -
      op: unknown
    -

    Returns op is "match" | "is" | "=" | "==" | "!=" | "<>" | ">" | ">=" | "<" | "<=" | "in" | "not in" | "is not" | "like" | "not like" | "ilike" | "not ilike" | "@>" | "<@" | "?" | "?&" | "!<" | "!>" | "<=>" | "!~" | "~" | "~*" | "!~*" | "@@" | "@@@" | "!!" | "<->" | "+" | "-" | "*" | "/" | "%" | "^" | "&" | "|" | "#" | "<<" | ">>" | "&&" | "||" | "exists" | "not exists" | "not"

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/isRawBuilder.html b/docs/functions/isRawBuilder.html deleted file mode 100644 index 26434d667..000000000 --- a/docs/functions/isRawBuilder.html +++ /dev/null @@ -1,440 +0,0 @@ -isRawBuilder | kysely
-
- -
-
-
-
- -

Function isRawBuilder

-
-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/logOnce.html b/docs/functions/logOnce.html deleted file mode 100644 index 5edcf438b..000000000 --- a/docs/functions/logOnce.html +++ /dev/null @@ -1,443 +0,0 @@ -logOnce | kysely
-
- -
-
-
-
- -

Function logOnce

-
-
    - -
  • -

    Use for system-level logging, such as deprecation messages. -Logs a message and ensures it won't be logged again.

    -
    -
    -

    Parameters

    -
      -
    • -
      message: string
    -

    Returns void

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/functions/sql-1.html b/docs/functions/sql-1.html deleted file mode 100644 index 2912d880f..000000000 --- a/docs/functions/sql-1.html +++ /dev/null @@ -1,483 +0,0 @@ -sql | kysely
-
- -
-
-
-
- -

Function sql

-
-
    - -
  • -

    Template tag for creating raw SQL snippets and queries.

    -
    import { sql } from 'kysely'

    const id = 123
    const snippet = sql<Person[]>`select * from person where id = ${id}` -
    -

    Substitutions (the things inside ${}) are automatically passed to the database -as parameters and are never interpolated to the SQL string. There's no need to worry -about SQL injection vulnerabilities. Substitutions can be values, other sql -expressions, queries and almost anything else Kysely can produce and they get -handled correctly. See the examples below.

    -

    If you need your substitutions to be interpreted as identifiers, value literals or -lists of things, see the ref, table, id, -lit, raw and join functions.

    -

    You can pass sql snippets returned by the sql tag pretty much anywhere. Whenever -something can't be done using the Kysely API, you should be able to drop down to -raw SQL using the sql tag. Here's an example query that uses raw sql in a bunch -of methods:

    -
    const persons = await db
    .selectFrom('person')
    .select(
    // If you use `sql` in a select statement, remember to call the `as`
    // method to give it an alias.
    sql<string>`concat(first_name, ' ', last_name)`.as('full_name')
    )
    .where(sql`birthdate between ${date1} and ${date2}`)
    // Here we assume we have list of nicknames for the person
    // (a list of strings) and we use the PostgreSQL `@>` operator
    // to test if all of them are valid nicknames for the user.
    .where('nicknames', '@>', sql`ARRAY[${sql.join(nicknames)}]`)
    .orderBy(sql`concat(first_name, ' ', last_name)`)
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select concat(first_name, ' ', last_name) as "full_name"
    from "person"
    where birthdate between $1 and $2
    and "nicknames" @> ARRAY[$3, $4, $5, $6, $7, $8, $9, $10]
    order by concat(first_name, ' ', last_name) -
    -

    SQL snippets can be executed by calling the execute method and passing a Kysely -instance as the only argument:

    -
    const result = await sql<Person[]>`select * from person`.execute(db)
    -
    -

    You can merge other sql expressions and queries using substitutions:

    -
    const petName = db.selectFrom('pet').select('name').limit(1)
    const fullName = sql`concat(first_name, ' ', last_name)`

    sql`
    select ${fullName} as full_name, ${petName} as pet_name
    from person
    ` -
    -

    Substitutions also handle ref, -ref and pretty much anything else you -throw at it. Here's an example of calling a function in a -type-safe way:

    -
    db.selectFrom('person')
    .select([
    'first_name',
    'last_name',
    (eb) => {
    // The `eb.ref` method is type-safe and only accepts
    // column references that are possible.
    const firstName = eb.ref('first_name')
    const lastName = eb.ref('last_name')

    const fullName = sql<string>`concat(${firstName}, ' ', ${lastName})`
    return fullName.as('full_name')
    }
    ]) -
    -

    don't know if that amount of ceremony is worth the small increase in -type-safety though... But it's possible.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      T = unknown

    -
    -

    Parameters

    -
      -
    • -
      sqlFragments: TemplateStringsArray
    • -
    • -
      Rest ...parameters: unknown[]
    -

    Returns RawBuilder<T>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 4a44d5242..0040c4191 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,699 +1,8 @@ -kysely
-
- -
-
-
-
-

kysely

-

Stand With Ukraine

-

Discord -Tests -License -Issues -Pull Requests -Vulnerabilities -Downloads -Bundle Size -Social

- - -

Kysely

- -

Kysely (pronounce “Key-Seh-Lee”) is a type-safe and autocompletion-friendly typescript SQL query builder. Inspired by -knex. Mainly developed for node.js but also runs on deno -and in the browser.

-

-

Kysely makes sure you only refer to tables and columns that are visible to the part of the query -you're writing. The result type only has the selected columns with correct types and aliases. As an -added bonus you get autocompletion for all that stuff.

-

As shown in the gif above, through the pure magic of modern typescript, Kysely is even able to parse -the alias given to pet.name and add the pet_name column to the result row type. Kysely is able to infer -column names, aliases and types from selected subqueries, joined subqueries, with statements and pretty -much anything you can think of.

-

Of course there are cases where things cannot be typed at compile time, and Kysely offers escape -hatches for these situations. See the sql template tag -and the DynamicModule for more info.

-

All API documentation is written in the typing files and you can simply cmd-click on the module, class -or method you're using to see it. The same documentation is also hosted here.

-

If you start using Kysely and can't find something you'd want to use, please open an issue or join our -discord server.

-

You can find a more thorough introduction here.

- - -

Table of contents

-
- - - -

Installation

-
-

Kysely currently works on PostgreSQL, MySQL and SQLite. You can install it using:

-
# PostgreSQL
npm install kysely pg

# MySQL
npm install kysely mysql2

# SQLite
npm install kysely better-sqlite3 -
-

More dialects will be added soon. Kysely also has a simple interface -for 3rd party dialects.

- - -

3rd party dialects

-
- - - -

Minimal example

-
-

All you need to do is define an interface for each table in the database and pass those -interfaces to the Kysely constructor:

-
import { Pool } from 'pg'
import {
Kysely,
PostgresDialect,
Generated,
ColumnType,
Selectable,
Insertable,
Updateable,
} from 'kysely'

interface PersonTable {
// Columns that are generated by the database should be marked
// using the `Generated` type. This way they are automatically
// made optional in inserts and updates.
id: Generated<number>

first_name: string
gender: 'male' | 'female' | 'other'

// If the column is nullable in the database, make its type nullable.
// Don't use optional properties. Optionality is always determined
// automatically by Kysely.
last_name: string | null

// You can specify a different type for each operation (select, insert and
// update) using the `ColumnType<SelectType, InsertType, UpdateType>`
// wrapper. Here we define a column `modified_at` that is selected as
// a `Date`, can optionally be provided as a `string` in inserts and
// can never be updated:
modified_at: ColumnType<Date, string | undefined, never>
}

interface PetTable {
id: Generated<number>
name: string
owner_id: number
species: 'dog' | 'cat'
}

interface MovieTable {
id: Generated<string>
stars: number
}

// Keys of this interface are table names.
interface Database {
person: PersonTable
pet: PetTable
movie: MovieTable
}

// You'd create one of these when you start your app.
const db = new Kysely<Database>({
// Use MysqlDialect for MySQL and SqliteDialect for SQLite.
dialect: new PostgresDialect({
pool: new Pool({
host: 'localhost',
database: 'kysely_test'
})
})
})

async function demo() {
const { id } = await db
.insertInto('person')
.values({ first_name: 'Jennifer', gender: 'female' })
.returning('id')
.executeTakeFirstOrThrow()

await db
.insertInto('pet')
.values({ name: 'Catto', species: 'cat', owner_id: id })
.execute()

const person = await db
.selectFrom('person')
.innerJoin('pet', 'pet.owner_id', 'person.id')
.select(['first_name', 'pet.name as pet_name'])
.where('person.id', '=', id)
.executeTakeFirst()

if (person) {
person.pet_name
}
} -
-
// You can extract the select, insert and update interfaces like this
// if you want (you don't need to):
type Person = Selectable<PersonTable>
type InsertablePerson = Insertable<PersonTable>
type UpdateablePerson = Updateable<PersonTable> -
- - -

Playground

-
-

@wirekang has created a playground for Kysely. You can use to quickly test stuff out and for creating code examples for your issues, PRs and discord messages.

- - -

Generating types

-
-

To work with Kysely, you're required to provide a database schema type definition to the Kysely constructor.

-

In many cases, defining your database schema definitions manually is good enough.

-

However, when building production applications, its best to stay aligned with the -database schema, by automatically generating the database schema type definitions.

-

There are several ways to do this using 3rd party libraries:

-
    -
  • kysely-codegen - This library -generates Kysely database schema type definitions by connecting to and introspecting -your database. This library works with all built-in dialects.

    -
  • -
  • prisma-kysely - This library generates -Kysely database schema type definitions from your existing Prisma schemas.

    -
  • -
- - -

Query examples

-
- - -

Select queries

-
-

You can find examples of select queries in the documentation of the -select method and -the where method -among other places.

- - -

Stream select query results

-
-

Currently only supported by postgres and mysql dialects.

-
import { Pool } from 'pg'
// or `import * as Cursor from 'pg-cursor'` depending on your tsconfig
import Cursor from 'pg-cursor'
import { Kysely, PostgresDialect } from 'kysely'

const db = new Kysely<Database>({
// PostgresDialect requires the Cursor dependency
dialect: new PostgresDialect({
pool: new Pool({
host: 'localhost',
database: 'kysely_test'
}),
cursor: Cursor
}),
// MysqlDialect doesn't require any special configuration
})

async function demo() {
for await (const adult of db.selectFrom('person')
.selectAll()
.where('age', '>', 18)
.stream()
) {
console.log(`Hello ${adult.first_name}!`)

if (adult.first_name === 'John') {
// After this line the db connection is released and no more
// rows are streamed from the database to the client
break;
}
}
} -
- - -

Update queries

-
-

See the set method and the -updateTable method -documentation.

- - -

Insert queries

-
-

See the values method and the -insertInto method -documentation.

- - -

Delete queries

-
-

See the deleteFrom method -documentation.

- - -

Recipes

-
-

The recipes folder contains a bunch of small tutorials -or "recipes" for common use cases.

- - - -

Migrations

-
-

Migration files should look like this:

-
import { Kysely } from 'kysely'

export async function up(db: Kysely<any>): Promise<void> {
// Migration code
}

export async function down(db: Kysely<any>): Promise<void> {
// Migration code
} -
-

The up function is called when you update your database schema to the next version and down -when you go back to previous version. The only argument for the functions is an instance of -Kysely<any>. It's important to use Kysely<any> and not Kysely<YourDatabase>.

-

Migrations should never depend on the current code of your app because they need to work even when the app -changes. Migrations need to be "frozen in time".

-

The migrations can use the Kysely.schema -module to modify the schema. Migrations can also run normal queries to modify data.

-

Execution order of the migrations is the alpabetical order of their names. An excellent way to name your -migrations is to prefix them with an ISO 8601 date string. A date prefix works well in large teams -where multiple team members may add migrations at the same time in parallel commits without knowing -about the other migrations.

-

You don't need to store your migrations as separate files if you don't want to. You can easily -implement your own MigrationProvider -and give it to the Migrator class -when you instantiate one.

- - -

PostgreSQL migration example

-
-
import { Kysely, sql } from 'kysely'

export async function up(db: Kysely<any>): Promise<void> {
await db.schema
.createTable('person')
.addColumn('id', 'serial', (col) => col.primaryKey())
.addColumn('first_name', 'varchar', (col) => col.notNull())
.addColumn('last_name', 'varchar')
.addColumn('gender', 'varchar(50)', (col) => col.notNull())
.addColumn('created_at', 'timestamp', (col) => col.defaultTo(sql`now()`).notNull())
.execute()

await db.schema
.createTable('pet')
.addColumn('id', 'serial', (col) => col.primaryKey())
.addColumn('name', 'varchar', (col) => col.notNull().unique())
.addColumn('owner_id', 'integer', (col) =>
col.references('person.id').onDelete('cascade').notNull()
)
.addColumn('species', 'varchar', (col) => col.notNull())
.execute()

await db.schema
.createIndex('pet_owner_id_index')
.on('pet')
.column('owner_id')
.execute()
}

export async function down(db: Kysely<any>): Promise<void> {
await db.schema.dropTable('pet').execute()
await db.schema.dropTable('person').execute()
} -
- - -

MySQL migration example

-
-
import { Kysely } from 'kysely'

export async function up(db: Kysely<any>): Promise<void> {
await db.schema
.createTable('person')
.addColumn('id', 'integer', (col) => col.autoIncrement().primaryKey())
.addColumn('first_name', 'varchar(255)', (col) => col.notNull())
.addColumn('last_name', 'varchar(255)')
.addColumn('gender', 'varchar(50)', (col) => col.notNull())
.execute()

await db.schema
.createTable('pet')
.addColumn('id', 'integer', (col) => col.autoIncrement().primaryKey())
.addColumn('name', 'varchar(255)', (col) => col.notNull().unique())
.addColumn('owner_id', 'integer', (col) => col.notNull())
.addColumn('species', 'varchar(255)', (col) => col.notNull())
.addForeignKeyConstraint(
'pet_owner_id_fk', ['owner_id'], 'person', ['id'],
(cb) => cb.onDelete('cascade')
)
.execute()

await db.schema
.createIndex('pet_owner_id_index')
.on('pet')
.column('owner_id')
.execute()
}

export async function down(db: Kysely<any>): Promise<void> {
await db.schema.dropTable('pet').execute()
await db.schema.dropTable('person').execute()
} -
-

You can then use

-
const migrator = new Migrator(migratorConfig);
await migrator.migrateToLatest(pathToMigrationsFolder) -
-

to run all migrations that have not yet been run. See the -Migrator -class's documentation for more info.

-

Kysely doesn't have a CLI for running migrations and probably never will. This is because Kysely's -migrations are also written in typescript. To run the migrations, you need to first build the -typescript code into javascript. A CLI would cause confusion over which migrations are being -run, the typescript ones or the javascript ones. If we added support for both, the CLI would -need to depend on a typescript compiler, which most production environments don't (and shouldn't) -have. You will probably want to add a simple migration script to your projects like this:

-
import * as path from 'path'
importPool } from 'pg'
import { promises as fs } from 'fs'
import {
Kysely,
Migrator,
PostgresDialect,
FileMigrationProvider
} from 'kysely'

async function migrateToLatest() {
const db = new Kysely<Database>({
dialect: new PostgresDialect({
pool: new Pool({
host: 'localhost',
database: 'kysely_test',
})
}),
})

const migrator = new Migrator({
db,
provider: new FileMigrationProvider({
fs,
path,
migrationFolder: 'some/path/to/migrations',
})
})

const { error, results } = await migrator.migrateToLatest()

results?.forEach((it) => {
if (it.status === 'Success') {
console.log(`migration "${it.migrationName}" was executed successfully`)
} else if (it.status === 'Error') {
console.error(`failed to execute migration "${it.migrationName}"`)
}
})

if (error) {
console.error('failed to migrate')
console.error(error)
process.exit(1)
}

await db.destroy()
}

migrateToLatest() -
-

The migration methods use a lock on the database level and parallel calls are executed serially. -This means that you can safely call migrateToLatest and other migration methods from multiple -server instances simultaneously and the migrations are guaranteed to only be executed once. The -locks are also automatically released if the migration process crashes or the connection to the -database fails.

- - -

Deno

-
-

Kysely doesn't include drivers for deno, but you can still use Kysely as a query builder -or implement your own driver:

-
// We use jsdeliver to get Kysely from npm.
import {
DummyDriver,
Generated,
Kysely,
PostgresAdapter,
PostgresIntrospector,
PostgresQueryCompiler,
} from 'https://cdn.jsdelivr.net/npm/kysely/dist/esm/index.js'

interface Person {
id: Generated<number>
first_name: string
last_name: string | null
}

interface Database {
person: Person
}

const db = new Kysely<Database>({
dialect: {
createAdapter() {
return new PostgresAdapter()
},
createDriver() {
// You need a driver to be able to execute queries. In this example
// we use the dummy driver that never does anything.
return new DummyDriver()
},
createIntrospector(db: Kysely<unknown>) {
return new PostgresIntrospector(db)
},
createQueryCompiler() {
return new PostgresQueryCompiler()
},
},
})

const query = db.selectFrom('person').select('id')
const sql = query.compile()

console.log(sql.sql) -
- - -

Browser

-
-

Kysely also runs in the browser:

-
import {
Kysely,
Generated,
DummyDriver,
SqliteAdapter,
SqliteIntrospector,
SqliteQueryCompiler,
} from 'kysely'

interface Person {
id: Generated<number>
first_name: string
last_name: string | null
}

interface Database {
person: Person
}

const db = new Kysely<Database>({
dialect: {
createAdapter() {
return new SqliteAdapter()
},
createDriver() {
return new DummyDriver()
},
createIntrospector(db: Kysely<unknown>) {
return new SqliteIntrospector(db)
},
createQueryCompiler() {
return new SqliteQueryCompiler()
},
},
})

window.addEventListener('load', () => {
const sql = db.selectFrom('person').select('id').compile()

const result = document.createElement('span')
result.id = 'result'
result.innerHTML = sql.sql

document.body.appendChild(result)
}) -
- - -

Why not just contribute to knex

-
-

Kysely is very similar to knex, but it also attempts to fix things that I personally find not-so-good -in knex. Bringing the type system and the changes to knex would mean very significant breaking changes -that aren't possible at this point of the project. Knex was also originally written for javascript and -the typescript typings were added afterwards. That always leads to compromises in the types. Designing -a library for typescript from the ground up produces much better and simpler types.

- - -

Contributors

-
-

- - - -
- Want to contribute? Check out our contribution guidelines. -

- -

- - Powered by Vercel - -

-
-
-

Generated using TypeDoc

-
\ No newline at end of file + + + + + + + + \ No newline at end of file diff --git a/docs/interfaces/AddColumnNode.html b/docs/interfaces/AddColumnNode.html deleted file mode 100644 index dcf0e33b1..000000000 --- a/docs/interfaces/AddColumnNode.html +++ /dev/null @@ -1,78 +0,0 @@ -AddColumnNode | kysely
-
- -
-
-
-
- -

Interface AddColumnNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
column: ColumnDefinitionNode
-
- -
kind: "AddColumnNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/AddConstraintNode.html b/docs/interfaces/AddConstraintNode.html deleted file mode 100644 index 08d6a7900..000000000 --- a/docs/interfaces/AddConstraintNode.html +++ /dev/null @@ -1,78 +0,0 @@ -AddConstraintNode | kysely
-
- -
-
-
-
- -

Interface AddConstraintNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
constraint: ConstraintNode
-
- -
kind: "AddConstraintNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/AggregateFunctionBuilderProps.html b/docs/interfaces/AggregateFunctionBuilderProps.html deleted file mode 100644 index 141b4a82d..000000000 --- a/docs/interfaces/AggregateFunctionBuilderProps.html +++ /dev/null @@ -1,67 +0,0 @@ -AggregateFunctionBuilderProps | kysely
-
- -
-
-
-
- -

Interface AggregateFunctionBuilderProps

-
-

Hierarchy

-
    -
  • AggregateFunctionBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
aggregateFunctionNode: AggregateFunctionNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/AggregateFunctionNode.html b/docs/interfaces/AggregateFunctionNode.html deleted file mode 100644 index 9c6d58cff..000000000 --- a/docs/interfaces/AggregateFunctionNode.html +++ /dev/null @@ -1,106 +0,0 @@ -AggregateFunctionNode | kysely
-
- -
-
-
-
- -

Interface AggregateFunctionNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
aggregated: readonly OperationNode[]
-
- -
distinct?: boolean
-
- -
filter?: WhereNode
-
- -
func: string
-
- -
kind: "AggregateFunctionNode"
-
- -
over?: OverNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/AliasNode.html b/docs/interfaces/AliasNode.html deleted file mode 100644 index 8f4e43c9f..000000000 --- a/docs/interfaces/AliasNode.html +++ /dev/null @@ -1,85 +0,0 @@ -AliasNode | kysely
-
- -
-
-
-
- -

Interface AliasNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
-
- -
kind: "AliasNode"
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/AliasedExpression.html b/docs/interfaces/AliasedExpression.html deleted file mode 100644 index 5c7294353..000000000 --- a/docs/interfaces/AliasedExpression.html +++ /dev/null @@ -1,128 +0,0 @@ -AliasedExpression | kysely
-
- -
-
-
-
- -

Interface AliasedExpression<T, A>

-
-

Just like Expression<T> but also holds an alias type A.

-

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.

- -

Example

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))
}
} -
-
-
-

Type Parameters

-
    -
  • -

    T

  • -
  • -

    A extends string

-
-

Hierarchy

-
-
-

Implemented by

-
-
-
-
- -
-
-

Accessors

-
-
-

Methods

-
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/AlterColumnNode.html b/docs/interfaces/AlterColumnNode.html deleted file mode 100644 index 8a126f3c6..000000000 --- a/docs/interfaces/AlterColumnNode.html +++ /dev/null @@ -1,120 +0,0 @@ -AlterColumnNode | kysely
-
- -
-
-
-
- -

Interface AlterColumnNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
- -
column: ColumnNode
-
- -
dataType?: OperationNode
-
- -
dataTypeExpression?: RawNode
-
- -
dropDefault?: true
-
- -
dropNotNull?: true
-
- -
kind: "AlterColumnNode"
-
- -
setDefault?: OperationNode
-
- -
setNotNull?: true
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/AlterTableBuilderProps.html b/docs/interfaces/AlterTableBuilderProps.html deleted file mode 100644 index a829669ad..000000000 --- a/docs/interfaces/AlterTableBuilderProps.html +++ /dev/null @@ -1,83 +0,0 @@ -AlterTableBuilderProps | kysely
-
- -
-
-
-
- -

Interface AlterTableBuilderProps

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
node: AlterTableNode
-
- -
queryId: QueryId
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/AlterTableColumnAlteringBuilderProps.html b/docs/interfaces/AlterTableColumnAlteringBuilderProps.html deleted file mode 100644 index bfe157e64..000000000 --- a/docs/interfaces/AlterTableColumnAlteringBuilderProps.html +++ /dev/null @@ -1,86 +0,0 @@ -AlterTableColumnAlteringBuilderProps | kysely
-
- -
-
-
-
- -

Interface AlterTableColumnAlteringBuilderProps

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
node: AlterTableNode
-
- -
queryId: QueryId
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/AlterTableNode.html b/docs/interfaces/AlterTableNode.html deleted file mode 100644 index 822c583ac..000000000 --- a/docs/interfaces/AlterTableNode.html +++ /dev/null @@ -1,113 +0,0 @@ -AlterTableNode | kysely
-
- -
-
-
-
- -

Interface AlterTableNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
- -
addConstraint?: AddConstraintNode
-
- -
columnAlterations?: readonly AlterTableColumnAlterationNode[]
-
- -
dropConstraint?: DropConstraintNode
-
- -
kind: "AlterTableNode"
-
- -
renameTo?: TableNode
-
- -
setSchema?: IdentifierNode
-
- -
table: TableNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/AndNode.html b/docs/interfaces/AndNode.html deleted file mode 100644 index 44665c220..000000000 --- a/docs/interfaces/AndNode.html +++ /dev/null @@ -1,85 +0,0 @@ -AndNode | kysely
-
- -
-
-
-
- -

Interface AndNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "AndNode"
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/BinaryOperationNode.html b/docs/interfaces/BinaryOperationNode.html deleted file mode 100644 index 3ab5e52ca..000000000 --- a/docs/interfaces/BinaryOperationNode.html +++ /dev/null @@ -1,92 +0,0 @@ -BinaryOperationNode | kysely
-
- -
-
-
-
- -

Interface BinaryOperationNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "BinaryOperationNode"
-
- -
leftOperand: OperationNode
-
- -
operator: OperationNode
-
- -
rightOperand: OperationNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CamelCasePluginOptions.html b/docs/interfaces/CamelCasePluginOptions.html deleted file mode 100644 index 039531fd1..000000000 --- a/docs/interfaces/CamelCasePluginOptions.html +++ /dev/null @@ -1,105 +0,0 @@ -CamelCasePluginOptions | kysely
-
- -
-
-
-
- -

Interface CamelCasePluginOptions

-
-

Hierarchy

-
    -
  • CamelCasePluginOptions
-
-
-
- -
-
-

Properties

-
- -
maintainNestedObjectKeys?: boolean
-

If true, nested object's keys will not be converted to camel case.

-

Defaults to false.

-
-
- -
underscoreBeforeDigits?: boolean
-

If true, an underscore is added before each digit when converting -camelCase to snake_case. For example foo12Bar => foo_12_bar and -foo_12_bar => foo12Bar

-

Defaults to false.

-
-
- -
underscoreBetweenUppercaseLetters?: boolean
-

If true, an underscore is added between consecutive upper case -letters when converting from camelCase to snake_case. For example -fooBAR => foo_b_a_r and foo_b_a_r => fooBAR.

-

Defaults to false.

-
-
- -
upperCase?: boolean
-

If true, camelCase is transformed into upper case SNAKE_CASE. -For example fooBar => FOO_BAR and FOO_BAR => fooBar

-

Defaults to false.

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CaseNode.html b/docs/interfaces/CaseNode.html deleted file mode 100644 index 634bfa6e7..000000000 --- a/docs/interfaces/CaseNode.html +++ /dev/null @@ -1,99 +0,0 @@ -CaseNode | kysely
-
- -
-
-
-
- -

Interface CaseNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
-
- -
isStatement?: boolean
-
- -
kind: "CaseNode"
-
- -
-
- -
when?: readonly WhenNode[]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CheckConstraintNode.html b/docs/interfaces/CheckConstraintNode.html deleted file mode 100644 index cb0d481da..000000000 --- a/docs/interfaces/CheckConstraintNode.html +++ /dev/null @@ -1,85 +0,0 @@ -CheckConstraintNode | kysely
-
- -
-
-
-
- -

Interface CheckConstraintNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
expression: OperationNode
-
- -
kind: "CheckConstraintNode"
-
- -
name?: IdentifierNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ColumnAlteringInterface.html b/docs/interfaces/ColumnAlteringInterface.html deleted file mode 100644 index 57dae2368..000000000 --- a/docs/interfaces/ColumnAlteringInterface.html +++ /dev/null @@ -1,158 +0,0 @@ -ColumnAlteringInterface | kysely
-
- -
-
-
-
- -

Interface ColumnAlteringInterface

-
-

Hierarchy

-
    -
  • ColumnAlteringInterface
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ColumnDefinitionNode.html b/docs/interfaces/ColumnDefinitionNode.html deleted file mode 100644 index 0e18a2982..000000000 --- a/docs/interfaces/ColumnDefinitionNode.html +++ /dev/null @@ -1,162 +0,0 @@ -ColumnDefinitionNode | kysely
-
- -
-
-
-
- -

Interface ColumnDefinitionNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
- -
autoIncrement?: boolean
-
- -
check?: CheckConstraintNode
-
- -
column: ColumnNode
-
- -
dataType: OperationNode
-
- -
defaultTo?: DefaultValueNode
-
- -
endModifiers?: readonly OperationNode[]
-
- -
frontModifiers?: readonly OperationNode[]
-
- -
generated?: GeneratedNode
-
- -
kind: "ColumnDefinitionNode"
-
- -
notNull?: boolean
-
- -
primaryKey?: boolean
-
- -
references?: ReferencesNode
-
- -
unique?: boolean
-
- -
unsigned?: boolean
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ColumnMetadata.html b/docs/interfaces/ColumnMetadata.html deleted file mode 100644 index 225e1f13f..000000000 --- a/docs/interfaces/ColumnMetadata.html +++ /dev/null @@ -1,110 +0,0 @@ -ColumnMetadata | kysely
-
- -
-
-
-
- -

Interface ColumnMetadata

-
-

Hierarchy

-
    -
  • ColumnMetadata
-
-
-
- -
-
-

Properties

-
- -
dataType: string
-

The data type of the column as reported by the database.

-

NOTE: This value is whatever the database engine returns and it will be - different on different dialects even if you run the same migrations. - For example integer datatype in a migration will produce int4 - on PostgreSQL, INTEGER on SQLite and int on MySQL.

-
-
- -
dataTypeSchema?: string
-

The schema this column's data type was created in.

-
-
- -
hasDefaultValue: boolean
-
- -
isAutoIncrementing: boolean
-
- -
isNullable: boolean
-
- -
name: string
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ColumnNode.html b/docs/interfaces/ColumnNode.html deleted file mode 100644 index 4b8fd54e1..000000000 --- a/docs/interfaces/ColumnNode.html +++ /dev/null @@ -1,78 +0,0 @@ -ColumnNode | kysely
-
- -
-
-
-
- -

Interface ColumnNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
column: IdentifierNode
-
- -
kind: "ColumnNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ColumnUpdateNode.html b/docs/interfaces/ColumnUpdateNode.html deleted file mode 100644 index 608aef547..000000000 --- a/docs/interfaces/ColumnUpdateNode.html +++ /dev/null @@ -1,85 +0,0 @@ -ColumnUpdateNode | kysely
-
- -
-
-
-
- -

Interface ColumnUpdateNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
column: ColumnNode
-
- -
kind: "ColumnUpdateNode"
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CommonTableExpressionNameNode.html b/docs/interfaces/CommonTableExpressionNameNode.html deleted file mode 100644 index e8c52a119..000000000 --- a/docs/interfaces/CommonTableExpressionNameNode.html +++ /dev/null @@ -1,85 +0,0 @@ -CommonTableExpressionNameNode | kysely
-
- -
-
-
-
- -

Interface CommonTableExpressionNameNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
columns?: readonly ColumnNode[]
-
- -
kind: "CommonTableExpressionNameNode"
-
- -
table: TableNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CommonTableExpressionNode.html b/docs/interfaces/CommonTableExpressionNode.html deleted file mode 100644 index f5cd3eaea..000000000 --- a/docs/interfaces/CommonTableExpressionNode.html +++ /dev/null @@ -1,85 +0,0 @@ -CommonTableExpressionNode | kysely
-
- -
-
-
-
- -

Interface CommonTableExpressionNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
expression: OperationNode
-
- -
kind: "CommonTableExpressionNode"
-
- -
name: CommonTableExpressionNameNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/Compilable.html b/docs/interfaces/Compilable.html deleted file mode 100644 index eb7207792..000000000 --- a/docs/interfaces/Compilable.html +++ /dev/null @@ -1,93 +0,0 @@ -Compilable | kysely
-
- -
-
-
-
- -

Interface Compilable<O>

-
-

Type Parameters

-
    -
  • -

    O = unknown

-
-

Hierarchy

-
    -
  • Compilable
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CompiledQuery.html b/docs/interfaces/CompiledQuery.html deleted file mode 100644 index 9ec0a932a..000000000 --- a/docs/interfaces/CompiledQuery.html +++ /dev/null @@ -1,87 +0,0 @@ -CompiledQuery | kysely
-
- -
-
-
-
- -

Interface CompiledQuery<O>

-
-

Type Parameters

-
    -
  • -

    O = unknown

-
-

Hierarchy

-
    -
  • CompiledQuery
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
parameters: readonly unknown[]
-
- -
-
- -
sql: string
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ConnectionProvider.html b/docs/interfaces/ConnectionProvider.html deleted file mode 100644 index 37835fe11..000000000 --- a/docs/interfaces/ConnectionProvider.html +++ /dev/null @@ -1,101 +0,0 @@ -ConnectionProvider | kysely
-
- -
-
-
-
- -

Interface ConnectionProvider

-
-

Hierarchy

-
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CreateIndexBuilderProps.html b/docs/interfaces/CreateIndexBuilderProps.html deleted file mode 100644 index 5f7ba054d..000000000 --- a/docs/interfaces/CreateIndexBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -CreateIndexBuilderProps | kysely
-
- -
-
-
-
- -

Interface CreateIndexBuilderProps

-
-

Hierarchy

-
    -
  • CreateIndexBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
node: CreateIndexNode
-
- -
queryId: QueryId
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CreateIndexNode.html b/docs/interfaces/CreateIndexNode.html deleted file mode 100644 index 1a7986cb8..000000000 --- a/docs/interfaces/CreateIndexNode.html +++ /dev/null @@ -1,120 +0,0 @@ -CreateIndexNode | kysely
-
- -
-
-
-
- -

Interface CreateIndexNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
- -
columns?: OperationNode[]
-
- -
ifNotExists?: boolean
-
- -
kind: "CreateIndexNode"
-
- -
name: IdentifierNode
-
- -
table?: TableNode
-
- -
unique?: boolean
-
- -
using?: RawNode
-
- -
where?: WhereNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CreateSchemaBuilderProps.html b/docs/interfaces/CreateSchemaBuilderProps.html deleted file mode 100644 index af2696dcb..000000000 --- a/docs/interfaces/CreateSchemaBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -CreateSchemaBuilderProps | kysely
-
- -
-
-
-
- -

Interface CreateSchemaBuilderProps

-
-

Hierarchy

-
    -
  • CreateSchemaBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
node: CreateSchemaNode
-
- -
queryId: QueryId
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CreateSchemaNode.html b/docs/interfaces/CreateSchemaNode.html deleted file mode 100644 index eac131a0d..000000000 --- a/docs/interfaces/CreateSchemaNode.html +++ /dev/null @@ -1,85 +0,0 @@ -CreateSchemaNode | kysely
-
- -
-
-
-
- -

Interface CreateSchemaNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
ifNotExists?: boolean
-
- -
kind: "CreateSchemaNode"
-
- -
schema: IdentifierNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CreateTableBuilderProps.html b/docs/interfaces/CreateTableBuilderProps.html deleted file mode 100644 index f4987f75e..000000000 --- a/docs/interfaces/CreateTableBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -CreateTableBuilderProps | kysely
-
- -
-
-
-
- -

Interface CreateTableBuilderProps

-
-

Hierarchy

-
    -
  • CreateTableBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
node: CreateTableNode
-
- -
queryId: QueryId
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CreateTableNode.html b/docs/interfaces/CreateTableNode.html deleted file mode 100644 index 7328e0449..000000000 --- a/docs/interfaces/CreateTableNode.html +++ /dev/null @@ -1,127 +0,0 @@ -CreateTableNode | kysely
-
- -
-
-
-
- -

Interface CreateTableNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
- -
columns: readonly ColumnDefinitionNode[]
-
- -
constraints?: readonly ConstraintNode[]
-
- -
endModifiers?: readonly OperationNode[]
-
- -
frontModifiers?: readonly OperationNode[]
-
- -
ifNotExists?: boolean
-
- -
kind: "CreateTableNode"
-
- -
onCommit?: string
-
- -
table: TableNode
-
- -
temporary?: boolean
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CreateTypeBuilderProps.html b/docs/interfaces/CreateTypeBuilderProps.html deleted file mode 100644 index 521d10514..000000000 --- a/docs/interfaces/CreateTypeBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -CreateTypeBuilderProps | kysely
-
- -
-
-
-
- -

Interface CreateTypeBuilderProps

-
-

Hierarchy

-
    -
  • CreateTypeBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
node: CreateTypeNode
-
- -
queryId: QueryId
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CreateTypeNode.html b/docs/interfaces/CreateTypeNode.html deleted file mode 100644 index 024347c32..000000000 --- a/docs/interfaces/CreateTypeNode.html +++ /dev/null @@ -1,85 +0,0 @@ -CreateTypeNode | kysely
-
- -
-
-
-
- -

Interface CreateTypeNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
enum?: ValueListNode
-
- -
kind: "CreateTypeNode"
-
- -
name: SchemableIdentifierNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CreateViewBuilderProps.html b/docs/interfaces/CreateViewBuilderProps.html deleted file mode 100644 index 388954aff..000000000 --- a/docs/interfaces/CreateViewBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -CreateViewBuilderProps | kysely
-
- -
-
-
-
- -

Interface CreateViewBuilderProps

-
-

Hierarchy

-
    -
  • CreateViewBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
node: CreateViewNode
-
- -
queryId: QueryId
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/CreateViewNode.html b/docs/interfaces/CreateViewNode.html deleted file mode 100644 index df4660b44..000000000 --- a/docs/interfaces/CreateViewNode.html +++ /dev/null @@ -1,120 +0,0 @@ -CreateViewNode | kysely
-
- -
-
-
-
- -

Interface CreateViewNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
- -
as?: RawNode | SelectQueryNode
-
- -
columns?: readonly ColumnNode[]
-
- -
ifNotExists?: boolean
-
- -
kind: "CreateViewNode"
-
- -
materialized?: boolean
-
- -
name: SchemableIdentifierNode
-
- -
orReplace?: boolean
-
- -
temporary?: boolean
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DataTypeNode.html b/docs/interfaces/DataTypeNode.html deleted file mode 100644 index e0f7e4b13..000000000 --- a/docs/interfaces/DataTypeNode.html +++ /dev/null @@ -1,78 +0,0 @@ -DataTypeNode | kysely
-
- -
-
-
-
- -

Interface DataTypeNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
dataType: ColumnDataType
-
- -
kind: "DataTypeNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DatabaseConnection.html b/docs/interfaces/DatabaseConnection.html deleted file mode 100644 index 3b0e089aa..000000000 --- a/docs/interfaces/DatabaseConnection.html +++ /dev/null @@ -1,106 +0,0 @@ -DatabaseConnection | kysely
-
- -
-
-
-
- -

Interface DatabaseConnection

-
-

A single connection to the database engine.

-

These are created by an instance of Driver.

-
-
-

Hierarchy

-
    -
  • DatabaseConnection
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DatabaseIntrospector.html b/docs/interfaces/DatabaseIntrospector.html deleted file mode 100644 index 9de873181..000000000 --- a/docs/interfaces/DatabaseIntrospector.html +++ /dev/null @@ -1,117 +0,0 @@ -DatabaseIntrospector | kysely
-
- -
-
-
-
- -

Interface DatabaseIntrospector

-
-

An interface for getting the database metadata (names of the tables and columns etc.)

-
-
-

Hierarchy

-
    -
  • DatabaseIntrospector
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DatabaseMetadata.html b/docs/interfaces/DatabaseMetadata.html deleted file mode 100644 index 30f6b16a9..000000000 --- a/docs/interfaces/DatabaseMetadata.html +++ /dev/null @@ -1,72 +0,0 @@ -DatabaseMetadata | kysely
-
- -
-
-
-
- -

Interface DatabaseMetadata

-
-

Hierarchy

-
    -
  • DatabaseMetadata
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
tables: TableMetadata[]
-

The tables and views found in the database.

-
    -
  • The propery isView can be used to tell them apart.
  • -
-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DatabaseMetadataOptions.html b/docs/interfaces/DatabaseMetadataOptions.html deleted file mode 100644 index 57cd0a6b1..000000000 --- a/docs/interfaces/DatabaseMetadataOptions.html +++ /dev/null @@ -1,70 +0,0 @@ -DatabaseMetadataOptions | kysely
-
- -
-
-
-
- -

Interface DatabaseMetadataOptions

-
-

Hierarchy

-
    -
  • DatabaseMetadataOptions
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
withInternalKyselyTables: boolean
-

If this is true, the metadata contains the internal kysely tables -such as the migration tables.

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DefaultInsertValueNode.html b/docs/interfaces/DefaultInsertValueNode.html deleted file mode 100644 index d39dd6ab2..000000000 --- a/docs/interfaces/DefaultInsertValueNode.html +++ /dev/null @@ -1,71 +0,0 @@ -DefaultInsertValueNode | kysely
-
- -
-
-
-
- -

Interface DefaultInsertValueNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "DefaultInsertValueNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DefaultValueNode.html b/docs/interfaces/DefaultValueNode.html deleted file mode 100644 index d21fad414..000000000 --- a/docs/interfaces/DefaultValueNode.html +++ /dev/null @@ -1,78 +0,0 @@ -DefaultValueNode | kysely
-
- -
-
-
-
- -

Interface DefaultValueNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
defaultValue: OperationNode
-
- -
kind: "DefaultValueNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DeleteQueryBuilderProps.html b/docs/interfaces/DeleteQueryBuilderProps.html deleted file mode 100644 index ae5a2533c..000000000 --- a/docs/interfaces/DeleteQueryBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -DeleteQueryBuilderProps | kysely
-
- -
-
-
-
- -

Interface DeleteQueryBuilderProps

-
-

Hierarchy

-
    -
  • DeleteQueryBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
queryId: QueryId
-
- -
queryNode: DeleteQueryNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DeleteQueryNode.html b/docs/interfaces/DeleteQueryNode.html deleted file mode 100644 index a0175fc80..000000000 --- a/docs/interfaces/DeleteQueryNode.html +++ /dev/null @@ -1,134 +0,0 @@ -DeleteQueryNode | kysely
-
- -
-
-
-
- -

Interface DeleteQueryNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
- -
explain?: ExplainNode
-
- -
from: FromNode
-
- -
joins?: readonly JoinNode[]
-
- -
kind: "DeleteQueryNode"
-
- -
limit?: LimitNode
-
- -
orderBy?: OrderByNode
-
- -
returning?: ReturningNode
-
- -
using?: UsingNode
-
- -
where?: WhereNode
-
- -
with?: WithNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/Dialect.html b/docs/interfaces/Dialect.html deleted file mode 100644 index 27a272210..000000000 --- a/docs/interfaces/Dialect.html +++ /dev/null @@ -1,128 +0,0 @@ -Dialect | kysely
-
- -
-
-
-
- -

Interface Dialect

-
-

A Dialect is the glue between Kysely and the underlying database engine.

-

See the built-in PostgresDialect as an example of a dialect. -Users can implement their own dialects and use them by passing it -in the dialect property.

-
-
-

Hierarchy

-
    -
  • Dialect
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DialectAdapter.html b/docs/interfaces/DialectAdapter.html deleted file mode 100644 index 609a07fa6..000000000 --- a/docs/interfaces/DialectAdapter.html +++ /dev/null @@ -1,157 +0,0 @@ -DialectAdapter | kysely
-
- -
-
-
-
- -

Interface DialectAdapter

-
-

A DialectAdapter encapsulates all differences between dialects outside -of Driver and QueryCompiler.

-

For example, some databases support transactional DDL and therefore we want -to run migrations inside a transaction, while other databases don't support -it. For that there's a supportsTransactionalDdl boolean in this interface.

-
-
-

Hierarchy

-
    -
  • DialectAdapter
-
-

Implemented by

-
-
-
-
- -
-
-

Properties

-
- -
supportsReturning: boolean
-

Whether or not this dialect supports the returning in inserts -updates and deletes.

-
-
- -
supportsTransactionalDdl: boolean
-

Whether or not this dialect supports transactional DDL.

-

If this is true, migrations are executed inside a transaction.

-
-
-

Methods

-
- -
    - -
  • -

    This method is used to acquire a lock for the migrations so that -it's not possible for two migration operations to run in parallel.

    -

    Most dialects have explicit locks that can be used, like advisory locks -in PostgreSQL and the get_lock function in MySQL.

    -

    If the dialect doesn't have explicit locks the lockTable -created by Kysely can be used instead. You can access it through the options object. -The lock table has two columns id and is_locked and there's only one row in the table -whose id is lockRowId. is_locked is an integer. Kysely -takes care of creating the lock table and inserting the one single row to it before this -method is executed. If the dialect supports schemas and the user has specified a custom -schema in their migration settings, the options object also contains the schema name in -lockTableSchema.

    -

    Here's an example of how you might implement this method for a dialect that doesn't -have explicit locks but supports FOR UPDATE row locks and transactional DDL:

    -
    {
    async acquireMigrationLock(db, options): Promise<void> {
    const queryDb = options.lockTableSchema
    ? db.withSchema(options.lockTableSchema)
    : db

    // Since our imaginary dialect supports transactional DDL and has
    // row locks, we can simply take a row lock here and it will guarantee
    // all subsequent calls to this method from other transactions will
    // wait until this transaction finishes.
    await queryDb
    .selectFrom(options.lockTable)
    .selectAll()
    .where('id', '=', options.lockRowId)
    .forUpdate()
    .execute()
    }
    } -
    -

    If supportsTransactionalDdl is true then the db passed to this method -is a transaction inside which the migrations will be executed. Otherwise -db is a single connection (session) that will be used to execute the -migrations.

    -
    -
    -

    Parameters

    -
    -

    Returns Promise<void>

-
- -
    - -
  • -

    Releases the migration lock. See acquireMigrationLock.

    -

    If supportsTransactionalDdl is true then the db passed to this method -is a transaction inside which the migrations were executed. Otherwise db -is a single connection (session) that was used to execute the migrations -and the acquireMigrationLock call.

    -
    -
    -

    Parameters

    -
    -

    Returns Promise<void>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/Driver.html b/docs/interfaces/Driver.html deleted file mode 100644 index 7b5acb1f4..000000000 --- a/docs/interfaces/Driver.html +++ /dev/null @@ -1,179 +0,0 @@ -Driver | kysely
-
- -
-
-
-
- -

Interface Driver

-
-

A Driver creates and releases database connections -and is also responsible for connection pooling (if the dialect supports pooling).

-
-
-

Hierarchy

-
    -
  • Driver
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Destroys the driver and releases all resources.

    -
    -

    Returns Promise<void>

-
- -
    - -
  • -

    Initializes the driver.

    -

    After calling this method the driver should be usable and acquireConnection etc. -methods should be callable.

    -
    -

    Returns Promise<void>

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DropColumnNode.html b/docs/interfaces/DropColumnNode.html deleted file mode 100644 index be33d7f1e..000000000 --- a/docs/interfaces/DropColumnNode.html +++ /dev/null @@ -1,78 +0,0 @@ -DropColumnNode | kysely
-
- -
-
-
-
- -

Interface DropColumnNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
column: ColumnNode
-
- -
kind: "DropColumnNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DropConstraintNode.html b/docs/interfaces/DropConstraintNode.html deleted file mode 100644 index 220445116..000000000 --- a/docs/interfaces/DropConstraintNode.html +++ /dev/null @@ -1,92 +0,0 @@ -DropConstraintNode | kysely
-
- -
-
-
-
- -

Interface DropConstraintNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
constraintName: IdentifierNode
-
- -
ifExists?: boolean
-
- -
kind: "DropConstraintNode"
-
- -
modifier?: "restrict" | "cascade"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DropIndexBuilderProps.html b/docs/interfaces/DropIndexBuilderProps.html deleted file mode 100644 index a00710959..000000000 --- a/docs/interfaces/DropIndexBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -DropIndexBuilderProps | kysely
-
- -
-
-
-
- -

Interface DropIndexBuilderProps

-
-

Hierarchy

-
    -
  • DropIndexBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
node: DropIndexNode
-
- -
queryId: QueryId
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DropIndexNode.html b/docs/interfaces/DropIndexNode.html deleted file mode 100644 index 02e413c7b..000000000 --- a/docs/interfaces/DropIndexNode.html +++ /dev/null @@ -1,99 +0,0 @@ -DropIndexNode | kysely
-
- -
-
-
-
- -

Interface DropIndexNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
cascade?: boolean
-
- -
ifExists?: boolean
-
- -
kind: "DropIndexNode"
-
- -
name: SchemableIdentifierNode
-
- -
table?: TableNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DropSchemaBuilderProps.html b/docs/interfaces/DropSchemaBuilderProps.html deleted file mode 100644 index e73c44a4b..000000000 --- a/docs/interfaces/DropSchemaBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -DropSchemaBuilderProps | kysely
-
- -
-
-
-
- -

Interface DropSchemaBuilderProps

-
-

Hierarchy

-
    -
  • DropSchemaBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
node: DropSchemaNode
-
- -
queryId: QueryId
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DropSchemaNode.html b/docs/interfaces/DropSchemaNode.html deleted file mode 100644 index 0087f18ae..000000000 --- a/docs/interfaces/DropSchemaNode.html +++ /dev/null @@ -1,92 +0,0 @@ -DropSchemaNode | kysely
-
- -
-
-
-
- -

Interface DropSchemaNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
cascade?: boolean
-
- -
ifExists?: boolean
-
- -
kind: "DropSchemaNode"
-
- -
schema: IdentifierNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DropTableBuilderProps.html b/docs/interfaces/DropTableBuilderProps.html deleted file mode 100644 index 7de1b4a89..000000000 --- a/docs/interfaces/DropTableBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -DropTableBuilderProps | kysely
-
- -
-
-
-
- -

Interface DropTableBuilderProps

-
-

Hierarchy

-
    -
  • DropTableBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
node: DropTableNode
-
- -
queryId: QueryId
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DropTableNode.html b/docs/interfaces/DropTableNode.html deleted file mode 100644 index af829064d..000000000 --- a/docs/interfaces/DropTableNode.html +++ /dev/null @@ -1,92 +0,0 @@ -DropTableNode | kysely
-
- -
-
-
-
- -

Interface DropTableNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
cascade?: boolean
-
- -
ifExists?: boolean
-
- -
kind: "DropTableNode"
-
- -
table: TableNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DropTypeBuilderProps.html b/docs/interfaces/DropTypeBuilderProps.html deleted file mode 100644 index c5b493d65..000000000 --- a/docs/interfaces/DropTypeBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -DropTypeBuilderProps | kysely
-
- -
-
-
-
- -

Interface DropTypeBuilderProps

-
-

Hierarchy

-
    -
  • DropTypeBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
node: DropTypeNode
-
- -
queryId: QueryId
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DropTypeNode.html b/docs/interfaces/DropTypeNode.html deleted file mode 100644 index d7b215fc2..000000000 --- a/docs/interfaces/DropTypeNode.html +++ /dev/null @@ -1,85 +0,0 @@ -DropTypeNode | kysely
-
- -
-
-
-
- -

Interface DropTypeNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
ifExists?: boolean
-
- -
kind: "DropTypeNode"
-
- -
name: SchemableIdentifierNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DropViewBuilderProps.html b/docs/interfaces/DropViewBuilderProps.html deleted file mode 100644 index 26ba45c8e..000000000 --- a/docs/interfaces/DropViewBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -DropViewBuilderProps | kysely
-
- -
-
-
-
- -

Interface DropViewBuilderProps

-
-

Hierarchy

-
    -
  • DropViewBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
node: DropViewNode
-
- -
queryId: QueryId
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/DropViewNode.html b/docs/interfaces/DropViewNode.html deleted file mode 100644 index 61e32b5c7..000000000 --- a/docs/interfaces/DropViewNode.html +++ /dev/null @@ -1,99 +0,0 @@ -DropViewNode | kysely
-
- -
-
-
-
- -

Interface DropViewNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
cascade?: boolean
-
- -
ifExists?: boolean
-
- -
kind: "DropViewNode"
-
- -
materialized?: boolean
-
- -
name: SchemableIdentifierNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ErrorLogEvent.html b/docs/interfaces/ErrorLogEvent.html deleted file mode 100644 index d3eba95ff..000000000 --- a/docs/interfaces/ErrorLogEvent.html +++ /dev/null @@ -1,88 +0,0 @@ -ErrorLogEvent | kysely
-
- -
-
-
-
- -

Interface ErrorLogEvent

-
-

Hierarchy

-
    -
  • ErrorLogEvent
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
error: unknown
-
- -
level: "error"
-
- -
query: CompiledQuery<unknown>
-
- -
queryDurationMillis: number
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ExplainNode.html b/docs/interfaces/ExplainNode.html deleted file mode 100644 index 42eb020cf..000000000 --- a/docs/interfaces/ExplainNode.html +++ /dev/null @@ -1,85 +0,0 @@ -ExplainNode | kysely
-
- -
-
-
-
- -

Interface ExplainNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
format?: ExplainFormat
-
- -
kind: "ExplainNode"
-
- -
options?: OperationNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/Explainable.html b/docs/interfaces/Explainable.html deleted file mode 100644 index 50da67269..000000000 --- a/docs/interfaces/Explainable.html +++ /dev/null @@ -1,102 +0,0 @@ -Explainable | kysely
-
- -
-
-
-
- -

Interface Explainable

-
-

Hierarchy

-
    -
  • Explainable
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
    - -
  • -

    Executes query with explain statement before the main query.

    -
    const explained = await db
    .selectFrom('person')
    .where('gender', '=', 'female')
    .selectAll()
    .explain('json') -
    -

    The generated SQL (MySQL):

    -
    explain format=json select * from `person` where `gender` = ?
    -
    -

    You can also execute explain analyze statements.

    -
    import { sql } from 'kysely'

    const explained = await db
    .selectFrom('person')
    .where('gender', '=', 'female')
    .selectAll()
    .explain('json', sql`analyze`) -
    -

    The generated SQL (PostgreSQL):

    -
    explain (analyze, format json) select * from "person" where "gender" = $1
    -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      O extends Record<string, any> = Record<string, any>

    -
    -

    Parameters

    -
    -

    Returns Promise<O[]>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/Expression.html b/docs/interfaces/Expression.html deleted file mode 100644 index 30a893088..000000000 --- a/docs/interfaces/Expression.html +++ /dev/null @@ -1,122 +0,0 @@ -Expression | kysely
-
- -
-
-
-
- -

Interface Expression<T>

-
-

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 sql template tag implement it.

-
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.

-
-
-

Type Parameters

-
    -
  • -

    T

-
-

Hierarchy

-
-
-

Implemented by

-
-
-
-
- -
-
-

Accessors

-
-
-

Methods

-
-
-

Accessors

-
- -
    -
  • get expressionType(): undefined | T
  • -
  • -

    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:

    -
    class SomeExpression<T> implements Expression<T> {
    get expressionType(): Tundefined {
    return undefined
    }
    } -
    -

    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>.

    -
    -

    Returns undefined | T

-
-

Methods

-
- -
    - -
  • -

    Creates the OperationNode that describes how to compile this expression into SQL.

    -

    If you are creating a custom expression, it's often easiest to use the sql -template tag to build the node:

    -
    class SomeExpression<T> implements Expression<T> {
    toOperationNode(): OperationNode {
    return sql`some sql here`.toOperationNode()
    }
    } -
    -
    -

    Returns OperationNode

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ExpressionBuilder.html b/docs/interfaces/ExpressionBuilder.html deleted file mode 100644 index 86e4b9018..000000000 --- a/docs/interfaces/ExpressionBuilder.html +++ /dev/null @@ -1,609 +0,0 @@ -ExpressionBuilder | kysely
-
- -
-
-
-
- -

Interface ExpressionBuilder<DB, TB>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-

Hierarchy

-
    -
  • ExpressionBuilder
-
-
-
- -
-
-

Accessors

-
fn -
-
-

Methods

-
-
-

Accessors

-
- -
    -
  • get fn(): FunctionModule<DB, TB>
  • -
  • -

    Returns a FunctionModule that can be used to write type safe function -calls.

    -

    The difference between this and 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. fn allows you to refer to columns in any -table of the database even if it doesn't produce valid SQL.

    -
    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(count('pet.id'), '>', 10)
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    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 -
    -
    -

    Returns FunctionModule<DB, TB>

-
-

Methods

-
- -
    - -
  • -

    Combines two or more expressions using the logical and operator.

    -

    This function returns an 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 with cmpr to create a WHERE expr1 AND expr2 AND expr3 -statement:

    -
    db.selectFrom('person')
    .selectAll('person')
    .where(({ and, cmpr }) => and([
    cmpr('first_name', '=', 'Jennifer'),
    cmpr('fist_name', '=', 'Arnold'),
    cmpr('fist_name', '=', 'Sylvester')
    ])) -
    -

    The generated SQL (PostgreSQL):

    -
    select "person".*
    from "person"
    where "first_name" = $1
    and "first_name" = $2
    and "first_name" = $3 -
    -
    -
    -

    Parameters

    -
    -

    Returns ExpressionWrapper<SqlBool>

-
- -
    - -
  • -

    Creates a binary expression.

    -

    See cmpr for creating binary comparison operations.

    -

    This function returns an Expression and can be used pretty much anywhere. -See the examples for a couple of possible use cases.

    - - -

    Examples

    -
    -

    In the following example bxp is used to increment an integer column:

    -
    db.updateTable('person')
    .set((eb) => ({
    age: eb.bxp('age', '+', 1)
    }))
    .where('id', '=', id) -
    -

    The generated SQL (PostgreSQL):

    -
    update "person"
    set "age" = "age" + $1
    where "id" = $2 -
    -

    By default the third argument is a value. ref can be used to -pass in a column reference instead:

    -
    db.updateTable('person')
    .set((eb) => ({
    age: eb.bxp('age', '+', eb.ref('age'))
    }))
    .where('id', '=', id) -
    -

    The generated SQL (PostgreSQL):

    -
    update "person"
    set "age" = "age" + "age"
    where "id" = $1 -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      RE extends string | Expression<any> | DynamicReferenceBuilder<any> | SelectQueryBuilder<any, any, {}> | SelectQueryBuilderFactory<DB, TB, {}> | ExpressionFactory<DB, TB, any>

    • -
    • -

      OP extends BinaryOperatorExpression

    -
    -

    Parameters

    -
    -

    Returns ExpressionWrapper<OP extends "match" | "is" | "=" | "==" | "!=" | "<>" | ">" | ">=" | "<" | "<=" | "in" | "not in" | "is not" | "like" | "not like" | "ilike" | "not ilike" | "@>" | "<@" | "?" | "?&" | "!<" | "!>" | "<=>" | "!~" | "~" | "~*" | "!~*" | "@@" | "@@@" | "!!" | "<->" ? SqlBool : ExtractTypeFromReferenceExpression<DB, TB, RE>>

-
- -
    - -
  • -

    Creates a case statement/operator.

    - - -

    Examples

    -
    -

    Kitchen sink example with 2 flavors of case operator:

    -
    import { sql } from 'kysely'

    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('martialStatus')
    .when('single')
    .then('Ms.')
    .else('Mrs.')
    .end()
    )
    .end()
    .as('title'),
    ])
    .executeTakeFirstOrThrow() -
    -

    The generated SQL (PostgreSQL):

    -
    select
    coalesce("last_name", "first_name") as "name",
    case
    when "gender" = $1 then $2
    when "gender" = $3 then
    case "martialStatus"
    when $4 then $5
    else $6
    end
    end as "title"
    from "person"
    where "id" = $7 -
    -
    -

    Returns CaseBuilder<DB, TB, unknown, never>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      C extends string | DynamicReferenceBuilder<any>

    -
    -

    Parameters

    -
      -
    • -
      column: C
    -

    Returns CaseBuilder<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, C>, never>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      O

    -
    -

    Parameters

    -
    -

    Returns CaseBuilder<DB, TB, O, never>

-
- -
    - -
  • -

    Creates a binary comparison expression.

    -

    This function returns an Expression and can be used pretty much anywhere. -See the examples for a couple of possible use cases.

    - -

    See

    bxp

    - - -

    Examples

    -
    -

    In this example we use cmpr and or to create a WHERE expr1 OR expr2 OR expr3 -statement:

    -
    db.selectFrom('person')
    .selectAll('person')
    .where(({ or, cmpr }) => or([
    cmpr('first_name', '=', 'Jennifer'),
    cmpr('fist_name', '=', 'Arnold'),
    cmpr('fist_name', '=', 'Sylvester')
    ])) -
    -

    The generated SQL (PostgreSQL):

    -
    select "person".*
    from "person"
    where "first_name" = $1
    or "first_name" = $2
    or "first_name" = $3 -
    -

    By default the third argument is a value. ref can be used to -pass in a column reference instead:

    -
    db.selectFrom('person')
    .selectAll('person')
    .where(({ or, cmpr, ref }) => or([
    cmpr('first_name', '=', ref('last_name')),
    cmpr('first_name', '=', ref('middle_name'))
    ])) -
    -

    The generated SQL (PostgreSQL):

    -
    select "person".*
    from "person"
    where "first_name" = "last_name"
    or "first_name" = "middle_name" -
    -
    -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
    -

    Returns ExpressionWrapper<O>

-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Combines two or more expressions using the logical or operator.

    -

    This function returns an 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 with cmpr to create a WHERE expr1 OR expr2 OR expr3 -statement:

    -
    db.selectFrom('person')
    .selectAll('person')
    .where(({ or, cmpr }) => or([
    cmpr('first_name', '=', 'Jennifer'),
    cmpr('fist_name', '=', 'Arnold'),
    cmpr('fist_name', '=', 'Sylvester')
    ])) -
    -

    The generated SQL (PostgreSQL):

    -
    select "person".*
    from "person"
    where "first_name" = $1
    or "first_name" = $2
    or "first_name" = $3 -
    -
    -
    -

    Parameters

    -
    -

    Returns ExpressionWrapper<SqlBool>

-
- -
    - -
  • -

    This can be used to reference columns.

    - - -

    Examples

    -
    -

    By default the third argument of bxp and cmpr is a value. -This function can be used to pass in a column reference instead:

    -
    db.selectFrom('person')
    .selectAll('person')
    .where(({ or, cmpr, ref }) => or([
    cmpr('first_name', '=', ref('last_name')),
    cmpr('first_name', '=', ref('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:

    -
    db.insertInto('person')
    .values(person)
    .onConflict((oc) => oc
    .column('id')
    .doUpdateSet(({ ref }) => ({
    first_name: ref('excluded.first_name'),
    last_name: ref('excluded.last_name')
    }))
    ) -
    -

    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:

    -
    db.update('pet').set((eb) => ({
    name: sql`concat(${eb.ref('pet.name')}, ${suffix})`
    })) -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      RE extends string

    -
    -

    Parameters

    -
      -
    • -
      reference: RE
    -

    Returns ExpressionWrapper<ExtractTypeFromReferenceExpression<DB, TB, RE>>

-
- -
    - -
  • -

    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 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:

    -
    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):

    -
    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.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      TE extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TE[]
    -

    Returns SelectQueryBuilder<DB, TB | ExtractTableAlias<DB, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, TB>

    -
    -

    Parameters

    -
      -
    • -
      from: TE[]
    -

    Returns SelectQueryBuilder<From<DB, TE>, FromTables<DB, TB, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string

    -
    -

    Parameters

    -
      -
    • -
      from: TE
    -

    Returns SelectQueryBuilder<DB, TB | ExtractTableAlias<DB, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends `${string} as ${string}`

    -
    -

    Parameters

    -
      -
    • -
      from: TE
    -

    Returns SelectQueryBuilder<DB & PickTableWithAlias<DB, TE>, TB | ExtractTableAlias<DB, TE>, {}>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      TE extends string | AliasedExpression<any, any> | AliasedExpressionFactory<DB, TB>

    -
    -

    Parameters

    -
      -
    • -
      from: TE
    -

    Returns SelectQueryBuilder<From<DB, TE>, FromTables<DB, TB, TE>, {}>

-
- -
-
- -
    - -
  • -

    Returns a value expression.

    -

    This can be used to pass in a value where a reference is taken by default.

    -

    This function returns an Expression and can be used pretty much anywhere.

    - - -

    Examples

    -
    -

    The cmpr function takes a reference by default as the first argument. val could -be used to pass in a value instead:

    -
    cmpr(val(38), '=', ref('age'))
    -
    -

    The generated SQL (PostgreSQL):

    -
    $1 = "age"
    -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      VE

    -
    -

    Parameters

    -
      -
    • -
      value: VE
    -

    Returns ExpressionWrapper<ExtractTypeFromValueExpressionOrList<VE>>

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/FileMigrationProviderFS.html b/docs/interfaces/FileMigrationProviderFS.html deleted file mode 100644 index 6ac7dc60e..000000000 --- a/docs/interfaces/FileMigrationProviderFS.html +++ /dev/null @@ -1,75 +0,0 @@ -FileMigrationProviderFS | kysely
-
- -
-
-
-
- -

Interface FileMigrationProviderFS

-
-

Hierarchy

-
    -
  • FileMigrationProviderFS
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/FileMigrationProviderPath.html b/docs/interfaces/FileMigrationProviderPath.html deleted file mode 100644 index 59bfd2709..000000000 --- a/docs/interfaces/FileMigrationProviderPath.html +++ /dev/null @@ -1,75 +0,0 @@ -FileMigrationProviderPath | kysely
-
- -
-
-
-
- -

Interface FileMigrationProviderPath

-
-

Hierarchy

-
    -
  • FileMigrationProviderPath
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/FileMigrationProviderProps.html b/docs/interfaces/FileMigrationProviderProps.html deleted file mode 100644 index 29f45cc2b..000000000 --- a/docs/interfaces/FileMigrationProviderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -FileMigrationProviderProps | kysely
-
- -
-
-
-
- -

Interface FileMigrationProviderProps

-
-

Hierarchy

-
    -
  • FileMigrationProviderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
-
- -
migrationFolder: string
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ForeignKeyConstraintBuilderInterface.html b/docs/interfaces/ForeignKeyConstraintBuilderInterface.html deleted file mode 100644 index 71390a06e..000000000 --- a/docs/interfaces/ForeignKeyConstraintBuilderInterface.html +++ /dev/null @@ -1,99 +0,0 @@ -ForeignKeyConstraintBuilderInterface | kysely
-
- -
-
-
-
- -

Interface ForeignKeyConstraintBuilderInterface<R>

-
-

Type Parameters

-
    -
  • -

    R

-
-

Hierarchy

-
    -
  • ForeignKeyConstraintBuilderInterface
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
    - -
  • -
    -

    Parameters

    -
      -
    • -
      onDelete: "no action" | "restrict" | "cascade" | "set null" | "set default"
    -

    Returns R

-
- -
    - -
  • -
    -

    Parameters

    -
      -
    • -
      onUpdate: "no action" | "restrict" | "cascade" | "set null" | "set default"
    -

    Returns R

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ForeignKeyConstraintNode.html b/docs/interfaces/ForeignKeyConstraintNode.html deleted file mode 100644 index afd42435b..000000000 --- a/docs/interfaces/ForeignKeyConstraintNode.html +++ /dev/null @@ -1,106 +0,0 @@ -ForeignKeyConstraintNode | kysely
-
- -
-
-
-
- -

Interface ForeignKeyConstraintNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
- -
columns: readonly ColumnNode[]
-
- -
kind: "ForeignKeyConstraintNode"
-
- -
name?: IdentifierNode
-
- -
onDelete?: "no action" | "restrict" | "cascade" | "set null" | "set default"
-
- -
onUpdate?: "no action" | "restrict" | "cascade" | "set null" | "set default"
-
- -
references: ReferencesNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/FromNode.html b/docs/interfaces/FromNode.html deleted file mode 100644 index d8a06534e..000000000 --- a/docs/interfaces/FromNode.html +++ /dev/null @@ -1,78 +0,0 @@ -FromNode | kysely
-
- -
-
-
-
- -

Interface FromNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
froms: readonly OperationNode[]
-
- -
kind: "FromNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/FunctionModule.html b/docs/interfaces/FunctionModule.html deleted file mode 100644 index 5a578b8ba..000000000 --- a/docs/interfaces/FunctionModule.html +++ /dev/null @@ -1,553 +0,0 @@ -FunctionModule | kysely
-
- -
-
-
-
- -

Interface FunctionModule<DB, TB>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-

Hierarchy

-
    -
  • FunctionModule
-
-
    - -
  • -

    Creates a function call.

    -

    To create an aggregate function call, use agg.

    - - -

    Examples

    -
    -
    db.selectFrom('person')
    .selectAll('person')
    .where(db.fn('upper', ['first_name']), '=', 'JENNIFER') -
    -

    The generated SQL (PostgreSQL):

    -
    select "person".*
    from "person"
    where upper("first_name") = $1 -
    -

    If you prefer readability over type-safety, you can always use raw sql:

    -
    db.selectFrom('person')
    .selectAll('person')
    .where(sql`upper(first_name)`, '=', 'JENNIFER') -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      T

    -
    -

    Parameters

    -
    -

    Returns ExpressionWrapper<T>

-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
    - -
  • -

    Creates an aggregate function call.

    -

    This is a specialized version of the fn method, that returns an AggregateFunctionBuilder -instance. A builder that allows you to chain additional methods such as distinct, -filterWhere and over.

    -

    See avg, count, countAll, max, min, sum -shortcuts of common aggregate functions.

    - - -

    Examples

    -
    -
    db.selectFrom('person')
    .select(({ fn }) => [
    fn.agg<number>('rank').over().as('rank'),
    fn.agg<string>('group_concat', ['first_name']).distinct().as('first_names')
    ]) -
    -

    The generated SQL (MySQL):

    -
    select rank() over() as "rank",
    group_concat(distinct "first_name") as "first_names"
    from "person" -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      O

    -
    -

    Parameters

    -
    -

    Returns AggregateFunctionBuilder<DB, TB, O>

-
- -
    - -
  • -

    Calls the avg function for the column 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 AggregateFunctionBuilder. An instance of this builder is -returned when calling this function.

    - - -

    Examples

    -
    -
    const { avg } = db.fn

    db.selectFrom('toy')
    .select(avg('price').as('avg_price'))
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select avg("price") as "avg_price" from "toy"
    -
    -

    You can limit column range to only columns participating in current query:

    -
    db.selectFrom('toy')
    .select((eb) => eb.fn.avg('price').as('avg_price'))
    .execute() -
    -

    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:

    -
    const { avg } = db.fn

    db.selectFrom('toy')
    .select(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 coalesce -function.

    -
    const { avg } = db.fn

    db.selectFrom('toy')
    .select(avg<number | null>('price').as('avg_price'))
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      O extends null | string | number = string | number

    • -
    • -

      C extends string | DynamicReferenceBuilder<any> = SimpleReferenceExpression<DB, TB>

    -
    -

    Parameters

    -
      -
    • -
      column: C
    -

    Returns 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

    -
    -
    const { coalesce } = db.fn

    db.selectFrom('participant')
    .select(coalesce('nickname', sql<string>`'<anonymous>'`).as('nickname'))
    .where('room_id', '=', roomId)
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select coalesce("nickname", '<anonymous>') as "nickname"
    from "participant" where "room_id" = $1 -
    -

    You can limit column range to only columns participating in current query:

    -
    db.selectFrom('participant')
    .select((eb) =>
    eb.fn.coalesce('nickname', sql<string>`'<anonymous>'`).as('nickname')
    )
    .where('room_id', '=', roomId)
    .execute() -
    -

    You can combine this function with other helpers in this module:

    -
    const { avg, coalesce } = db.fn

    db.selectFrom('person')
    .select(coalesce(avg<number | null>('age'), sql<number>`0`).as('avg_age'))
    .where('first_name', '=', 'Jennifer')
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select coalesce(avg("age"), 0) as "avg_age" from "person" where "first_name" = $1
    -
    -
    -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      value: V
    • -
    • -
      Rest ...otherValues: OV
    -

    Returns ExpressionWrapper<CoalesceReferenceExpressionList<DB, TB, [V, ...OV[]]>>

-
- -
    - -
  • -

    Calls the count function for the column 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 countAll.

    -

    For additional functionality such as distinct, filtering and window functions, -refer to AggregateFunctionBuilder. An instance of this builder is -returned when calling this function.

    - - -

    Examples

    -
    -
    const { count } = db.fn

    db.selectFrom('toy')
    .select(count('id').as('num_toys'))
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    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:

    -
    const { count } = db.fn

    db.selectFrom('toy')
    .select(count<number>('id').as('num_toys'))
    .execute() -
    -

    You can limit column range to only columns participating in current query:

    -
    db.selectFrom('toy')
    .select((eb) => eb.fn.count('id').as('num_toys'))
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      O extends string | number | bigint

    • -
    • -

      C extends string | DynamicReferenceBuilder<any> = SimpleReferenceExpression<DB, TB>

    -
    -

    Parameters

    -
      -
    • -
      column: C
    -

    Returns 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 count.

    -

    For additional functionality such as filtering and window functions, refer -to AggregateFunctionBuilder. An instance of this builder is returned -when calling this function.

    - - -

    Examples

    -
    -
    const { countAll } = db.fn

    db.selectFrom('toy')
    .select(countAll().as('num_toys'))
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    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:

    -
    const { countAll } = db.fn

    db.selectFrom('toy')
    .select(countAll<number>().as('num_toys'))
    .execute() -
    -

    Some databases, such as PostgreSQL, support scoping the function to a specific -table:

    -
    const { countAll } = db.fn

    db.selectFrom('toy')
    .innerJoin('pet', 'pet.id', 'toy.pet_id')
    .select(countAll('toy').as('num_toys'))
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select count("toy".*) as "num_toys"
    from "toy" inner join "pet" on "pet"."id" = "toy"."pet_id" -
    -

    You can limit table range to only tables participating in current query:

    -
    db.selectFrom('toy')
    .innerJoin('pet', 'pet.id', 'toy.pet_id')
    .select((eb) => eb.fn.countAll('toy').as('num_toys'))
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      O extends string | number | bigint

    • -
    • -

      T extends string | number | symbol = TB

    -
    -

    Parameters

    -
      -
    • -
      table: T
    -

    Returns AggregateFunctionBuilder<DB, TB, O>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      O extends string | number | bigint

    -

    Returns AggregateFunctionBuilder<DB, TB, O>

-
- -
    - -
  • -

    Calls the max function for the column 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 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

    -
    -
    const { max } = db.fn

    db.selectFrom('toy')
    .select(max('price').as('max_price'))
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select max("price") as "max_price" from "toy"
    -
    -

    You can limit column range to only columns participating in current query:

    -
    db.selectFrom('toy')
    .select((eb) => eb.fn.max('price').as('max_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 coalesce -function.

    -
    const { max } = db.fn

    db.selectFrom('toy')
    .select(max<number | null, 'price'>('price').as('max_price'))
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      O extends null | string | number | bigint = any

    • -
    • -

      C extends string = StringReference<DB, TB>

    -
    -

    Parameters

    -
      -
    • -
      column: OutputBoundStringReference<DB, TB, C, O>
    -

    Returns StringReferenceBoundAggregateFunctionBuilder<DB, TB, C, O>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      O extends null | string | number | bigint = string | number | bigint

    -
    -

    Parameters

    -
      -
    • -
      column: DynamicReferenceBuilder<never>
    -

    Returns AggregateFunctionBuilder<DB, TB, O>

-
- -
    - -
  • -

    Calls the min function for the column 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 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

    -
    -
    const { min } = db.fn

    db.selectFrom('toy')
    .select(min('price').as('min_price'))
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select min("price") as "min_price" from "toy"
    -
    -

    You can limit column range to only columns participating in current query:

    -
    db.selectFrom('toy')
    .select((eb) => eb.fn.min('price').as('min_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 coalesce -function.

    -
    const { min } = db.fn

    db.selectFrom('toy')
    .select(min<number | null, 'price'>('price').as('min_price'))
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      O extends null | string | number | bigint = any

    • -
    • -

      C extends string = StringReference<DB, TB>

    -
    -

    Parameters

    -
      -
    • -
      column: OutputBoundStringReference<DB, TB, C, O>
    -

    Returns StringReferenceBoundAggregateFunctionBuilder<DB, TB, C, O>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      O extends null | string | number | bigint = string | number | bigint

    -
    -

    Parameters

    -
      -
    • -
      column: DynamicReferenceBuilder<never>
    -

    Returns AggregateFunctionBuilder<DB, TB, O>

-
- -
    - -
  • -

    Calls the sum function for the column 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 AggregateFunctionBuilder. An instance of this builder is -returned when calling this function.

    - - -

    Examples

    -
    -
    const { sum } = db.fn

    db.selectFrom('toy')
    .select(sum('price').as('total_price'))
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select sum("price") as "total_price" from "toy"
    -
    -

    You can limit column range to only columns participating in current query:

    -
    db.selectFrom('toy')
    .select((eb) => eb.fn.sum('price').as('total_price'))
    .execute() -
    -

    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:

    -
    const { sum } = db.fn

    db.selectFrom('toy')
    .select(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 coalesce -function.

    -
    const { sum } = db.fn

    db.selectFrom('toy')
    .select(sum<number | null>('price').as('total_price'))
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      O extends null | string | number | bigint = string | number | bigint

    • -
    • -

      C extends string | DynamicReferenceBuilder<any> = SimpleReferenceExpression<DB, TB>

    -
    -

    Parameters

    -
      -
    • -
      column: C
    -

    Returns AggregateFunctionBuilder<DB, TB, O>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/GeneratedNode.html b/docs/interfaces/GeneratedNode.html deleted file mode 100644 index a1234b6cf..000000000 --- a/docs/interfaces/GeneratedNode.html +++ /dev/null @@ -1,106 +0,0 @@ -GeneratedNode | kysely
-
- -
-
-
-
- -

Interface GeneratedNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
- -
always?: boolean
-
- -
byDefault?: boolean
-
- -
expression?: OperationNode
-
- -
identity?: boolean
-
- -
kind: "GeneratedNode"
-
- -
stored?: boolean
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/GroupByItemNode.html b/docs/interfaces/GroupByItemNode.html deleted file mode 100644 index 2381e986a..000000000 --- a/docs/interfaces/GroupByItemNode.html +++ /dev/null @@ -1,78 +0,0 @@ -GroupByItemNode | kysely
-
- -
-
-
-
- -

Interface GroupByItemNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
groupBy: OperationNode
-
- -
kind: "GroupByItemNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/GroupByNode.html b/docs/interfaces/GroupByNode.html deleted file mode 100644 index a373061f2..000000000 --- a/docs/interfaces/GroupByNode.html +++ /dev/null @@ -1,78 +0,0 @@ -GroupByNode | kysely
-
- -
-
-
-
- -

Interface GroupByNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
items: readonly GroupByItemNode[]
-
- -
kind: "GroupByNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/HavingInterface.html b/docs/interfaces/HavingInterface.html deleted file mode 100644 index 7f23531f3..000000000 --- a/docs/interfaces/HavingInterface.html +++ /dev/null @@ -1,287 +0,0 @@ -HavingInterface | kysely
-
- -
-
-
-
- -

Interface HavingInterface<DB, TB>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-

Hierarchy

-
    -
  • HavingInterface
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/HavingNode.html b/docs/interfaces/HavingNode.html deleted file mode 100644 index b482f483d..000000000 --- a/docs/interfaces/HavingNode.html +++ /dev/null @@ -1,78 +0,0 @@ -HavingNode | kysely
-
- -
-
-
-
- -

Interface HavingNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
-
- -
kind: "HavingNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/IdentifierNode.html b/docs/interfaces/IdentifierNode.html deleted file mode 100644 index b0bbd8923..000000000 --- a/docs/interfaces/IdentifierNode.html +++ /dev/null @@ -1,78 +0,0 @@ -IdentifierNode | kysely
-
- -
-
-
-
- -

Interface IdentifierNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "IdentifierNode"
-
- -
name: string
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/InsertQueryBuilderProps.html b/docs/interfaces/InsertQueryBuilderProps.html deleted file mode 100644 index d6f6cef65..000000000 --- a/docs/interfaces/InsertQueryBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -InsertQueryBuilderProps | kysely
-
- -
-
-
-
- -

Interface InsertQueryBuilderProps

-
-

Hierarchy

-
    -
  • InsertQueryBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
queryId: QueryId
-
- -
queryNode: InsertQueryNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/InsertQueryNode.html b/docs/interfaces/InsertQueryNode.html deleted file mode 100644 index 18116cf60..000000000 --- a/docs/interfaces/InsertQueryNode.html +++ /dev/null @@ -1,141 +0,0 @@ -InsertQueryNode | kysely
-
- -
-
-
-
- -

Interface InsertQueryNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
- -
columns?: readonly ColumnNode[]
-
- -
explain?: ExplainNode
-
- -
ignore?: boolean
-
- -
into: TableNode
-
- -
kind: "InsertQueryNode"
-
- -
onConflict?: OnConflictNode
-
- -
onDuplicateKey?: OnDuplicateKeyNode
-
- -
replace?: boolean
-
- -
returning?: ReturningNode
-
- -
values?: OperationNode
-
- -
with?: WithNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/JoinBuilderProps.html b/docs/interfaces/JoinBuilderProps.html deleted file mode 100644 index 3b7a0667d..000000000 --- a/docs/interfaces/JoinBuilderProps.html +++ /dev/null @@ -1,67 +0,0 @@ -JoinBuilderProps | kysely
-
- -
-
-
-
- -

Interface JoinBuilderProps

-
-

Hierarchy

-
    -
  • JoinBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
joinNode: JoinNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/JoinNode.html b/docs/interfaces/JoinNode.html deleted file mode 100644 index 8a8163c33..000000000 --- a/docs/interfaces/JoinNode.html +++ /dev/null @@ -1,92 +0,0 @@ -JoinNode | kysely
-
- -
-
-
-
- -

Interface JoinNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
joinType: JoinType
-
- -
kind: "JoinNode"
-
- -
on?: OnNode
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/KyselyConfig.html b/docs/interfaces/KyselyConfig.html deleted file mode 100644 index 5f90f7aec..000000000 --- a/docs/interfaces/KyselyConfig.html +++ /dev/null @@ -1,93 +0,0 @@ -KyselyConfig | kysely
-
- -
-
-
-
- -

Interface KyselyConfig

-
-

Hierarchy

-
    -
  • KyselyConfig
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
dialect: Dialect
-
- -
log?: LogConfig
-

A list of log levels to log or a custom logger function.

-

Currently there's only two levels: query and error. -This will be expanded based on user feedback later.

- - -

Examples

-
-
const db = new Kysely<Database>({
dialect: new PostgresDialect(postgresConfig),
log: ['query', 'error']
}) -
-
const db = new Kysely<Database>({
dialect: new PostgresDialect(postgresConfig),
log(event): void {
if (event.level === 'query') {
console.log(event.query.sql)
console.log(event.query.parameters)
}
}
}) -
-
-
- -
plugins?: KyselyPlugin[]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/KyselyPlugin.html b/docs/interfaces/KyselyPlugin.html deleted file mode 100644 index e5daf6095..000000000 --- a/docs/interfaces/KyselyPlugin.html +++ /dev/null @@ -1,112 +0,0 @@ -KyselyPlugin | kysely
-
- -
-
-
-
- -

Interface KyselyPlugin

-
-

Hierarchy

-
    -
  • KyselyPlugin
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
- -
    - -
  • -

    This is called for each query before it is executed. You can modify the query by -transforming its OperationNode tree provided in args.node -and returning the transformed tree. You'd usually want to use an OperationNodeTransformer -for this.

    -

    If you need to pass some query-related data between this method and transformResult you -can use a WeakMap with args.queryId as the key:

    -
    const plugin = {
    data: new WeakMap<QueryId, SomeData>(),

    transformQuery(args: PluginTransformQueryArgs): RootOperationNode {
    this.data.set(args.queryId, something)
    return args.node
    },

    transformResult(args: PluginTransformResultArgs): QueryResult<UnknownRow> {
    const data = this.data.get(args.queryId)
    return args.result
    }
    } -
    -

    You should use a WeakMap instead of a Map or some other strong references because transformQuery -is not always matched by a call to transformResult which would leave orphaned items in the map -and cause a memory leak.

    -
    -
    -

    Parameters

    -
    -

    Returns RootOperationNode

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/KyselyProps.html b/docs/interfaces/KyselyProps.html deleted file mode 100644 index 2902a6960..000000000 --- a/docs/interfaces/KyselyProps.html +++ /dev/null @@ -1,88 +0,0 @@ -KyselyProps | kysely
-
- -
-
-
-
- -

Interface KyselyProps

-
-

Hierarchy

-
    -
  • KyselyProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
config: KyselyConfig
-
- -
dialect: Dialect
-
- -
driver: Driver
-
- -
executor: QueryExecutor
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/LimitNode.html b/docs/interfaces/LimitNode.html deleted file mode 100644 index 28ab26b97..000000000 --- a/docs/interfaces/LimitNode.html +++ /dev/null @@ -1,78 +0,0 @@ -LimitNode | kysely
-
- -
-
-
-
- -

Interface LimitNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "LimitNode"
-
- -
limit: ValueNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ListNode.html b/docs/interfaces/ListNode.html deleted file mode 100644 index 6b1f6745d..000000000 --- a/docs/interfaces/ListNode.html +++ /dev/null @@ -1,78 +0,0 @@ -ListNode | kysely
-
- -
-
-
-
- -

Interface ListNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
items: readonly OperationNode[]
-
- -
kind: "ListNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/Migration.html b/docs/interfaces/Migration.html deleted file mode 100644 index 20f64e900..000000000 --- a/docs/interfaces/Migration.html +++ /dev/null @@ -1,94 +0,0 @@ -Migration | kysely
-
- -
-
-
-
- -

Interface Migration

-
-

Hierarchy

-
    -
  • Migration
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
    - -
  • -

    An optional down method.

    -

    If you don't provide a down method, the migration is skipped when -migrating down.

    -
    -
    -

    Parameters

    -
    -

    Returns Promise<void>

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/MigrationInfo.html b/docs/interfaces/MigrationInfo.html deleted file mode 100644 index e6d65f4b6..000000000 --- a/docs/interfaces/MigrationInfo.html +++ /dev/null @@ -1,88 +0,0 @@ -MigrationInfo | kysely
-
- -
-
-
-
- -

Interface MigrationInfo

-
-

Hierarchy

-
    -
  • MigrationInfo
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executedAt?: Date
-

When was the migration executed.

-

If this is undefined, the migration hasn't been executed yet.

-
-
- -
migration: Migration
-

The actual migration.

-
-
- -
name: string
-

Name of the migration.

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/MigrationLockOptions.html b/docs/interfaces/MigrationLockOptions.html deleted file mode 100644 index 5d5d1b5a2..000000000 --- a/docs/interfaces/MigrationLockOptions.html +++ /dev/null @@ -1,89 +0,0 @@ -MigrationLockOptions | kysely
-
- -
-
-
-
- -

Interface MigrationLockOptions

-
-

Hierarchy

-
    -
  • MigrationLockOptions
-
-
-
- -
-
-

Properties

-
- -
lockRowId: string
-

The id of the only row in the migration lock table.

-
-
- -
lockTable: string
-

The name of the migration lock table.

-
-
- -
lockTableSchema?: string
-

The schema in which the migration lock table lives. This is only -defined if the user has specified a custom schema in the migration -settings.

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/MigrationProvider.html b/docs/interfaces/MigrationProvider.html deleted file mode 100644 index 409816954..000000000 --- a/docs/interfaces/MigrationProvider.html +++ /dev/null @@ -1,85 +0,0 @@ -MigrationProvider | kysely
-
- -
-
-
-
- -

Interface MigrationProvider

-
-

Hierarchy

-
    -
  • MigrationProvider
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
    - -
  • -

    Returns all migrations, old and new.

    -

    For example if you have your migrations in a folder as separate files, -you can implement this method to return all migration in that folder -as Migration objects.

    -

    Kysely already has a built-in FileMigrationProvider for node.js -that does exactly that.

    -

    The keys of the returned object are migration names and values are the -migrations. The order of the migrations is determined by the alphabetical -order of the migration names. The items in the object don't need to be -sorted, they are sorted by Kysely.

    -
    -

    Returns Promise<Record<string, Migration>>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/MigrationResult.html b/docs/interfaces/MigrationResult.html deleted file mode 100644 index e424831a3..000000000 --- a/docs/interfaces/MigrationResult.html +++ /dev/null @@ -1,98 +0,0 @@ -MigrationResult | kysely
-
- -
-
-
-
- -

Interface MigrationResult

-
-

Hierarchy

-
    -
  • MigrationResult
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
direction: "Down" | "Up"
-

The direction in which this migration was executed.

-
-
- -
migrationName: string
-
- -
status: "NotExecuted" | "Success" | "Error"
-

The execution status.

-
    -
  • Success means the migration was successfully executed. Note that -if any of the later migrations in the MigrationResult.results -list failed (have status Error) AND the dialect supports transactional -DDL, even the successfull migrations were rolled back.

    -
  • -
  • Error means the migration failed. In this case the -MigrationResult.error contains the error.

    -
  • -
  • NotExecuted means that the migration was supposed to be executed -but wasn't because an earlier migration failed.

    -
  • -
-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/MigrationResultSet.html b/docs/interfaces/MigrationResultSet.html deleted file mode 100644 index 68998ae10..000000000 --- a/docs/interfaces/MigrationResultSet.html +++ /dev/null @@ -1,96 +0,0 @@ -MigrationResultSet | kysely
-
- -
-
-
-
- -

Interface MigrationResultSet

-
-

All migration methods (migrateTo, -migrateToLatest etc.) never -throw but return this object instead.

-
-
-

Hierarchy

-
    -
  • MigrationResultSet
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
error?: unknown
-

This is defined if something went wrong.

-

An error may have occurred in one of the migrations in which case the -results list contains an item with status === 'Error' to -indicate which migration failed.

-

An error may also have occurred before Kysely was able to figure out -which migrations should be executed, in which case the results -list is undefined.

-
-
- -
results?: MigrationResult[]
-

MigrationResult for each individual migration that was supposed -to be executed by the operation.

-

If all went well, each result's status is Success. If some migration -failed, the failed migration's result's status is Error and all -results after that one have status ´NotExecuted`.

-

This property can be undefined if an error occurred before Kysely was -able to figure out which migrations should be executed.

-

If this list is empty, there were no migrations to execute.

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/MigratorProps.html b/docs/interfaces/MigratorProps.html deleted file mode 100644 index 3afec9e0f..000000000 --- a/docs/interfaces/MigratorProps.html +++ /dev/null @@ -1,126 +0,0 @@ -MigratorProps | kysely
-
- -
-
-
-
- -

Interface MigratorProps

-
-

Hierarchy

-
    -
  • MigratorProps
-
-
-
- -
-
-

Properties

-
- -
db: Kysely<any>
-
- -
migrationLockTableName?: string
-

The name of the internal migration lock table. Defaults to kysely_migration_lock.

-

If you do specify this, you need to ALWAYS use the same value. Kysely doesn't -support changing the table on the fly. If you run the migrator even once with a -table name X and then change the table name to Y, kysely will create a new empty -lock table.

-

If you do specify this, ALWAYS ALWAYS use the same value from the beginning of -the project, to the end of time or prepare to manually migrate the migration -tables.

-
-
- -
migrationTableName?: string
-

The name of the internal migration table. Defaults to kysely_migration.

-

If you do specify this, you need to ALWAYS use the same value. Kysely doesn't -support changing the table on the fly. If you run the migrator even once with a -table name X and then change the table name to Y, kysely will create a new empty -migration table and attempt to run the migrations again, which will obviously -fail.

-

If you do specify this, ALWAYS ALWAYS use the same value from the beginning of -the project, to the end of time or prepare to manually migrate the migration -tables.

-
-
- -
migrationTableSchema?: string
-

The schema of the internal migration tables. Defaults to the default schema -on dialects that support schemas.

-

If you do specify this, you need to ALWAYS use the same value. Kysely doesn't -support changing the schema on the fly. If you run the migrator even once with a -schema name X and then change the schema name to Y, kysely will create a new empty -migration tables in the new schema and attempt to run the migrations again, which -will obviously fail.

-

If you do specify this, ALWAYS ALWAYS use the same value from the beginning of -the project, to the end of time or prepare to manually migrate the migration -tables.

-

This only works on postgres.

-
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ModifyColumnNode.html b/docs/interfaces/ModifyColumnNode.html deleted file mode 100644 index 829bc484f..000000000 --- a/docs/interfaces/ModifyColumnNode.html +++ /dev/null @@ -1,78 +0,0 @@ -ModifyColumnNode | kysely
-
- -
-
-
-
- -

Interface ModifyColumnNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
column: ColumnDefinitionNode
-
- -
kind: "ModifyColumnNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/MysqlDialectConfig.html b/docs/interfaces/MysqlDialectConfig.html deleted file mode 100644 index 278e234e3..000000000 --- a/docs/interfaces/MysqlDialectConfig.html +++ /dev/null @@ -1,97 +0,0 @@ -MysqlDialectConfig | kysely
-
- -
-
-
-
- -

Interface MysqlDialectConfig

-
-
-
-

Hierarchy

-
    -
  • MysqlDialectConfig
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
onCreateConnection?: ((connection: DatabaseConnection) => Promise<void>)
-
-

Type declaration

-
-
- -
pool: MysqlPool | (() => Promise<MysqlPool>)
-

A mysql2 Pool instance or a function that returns one.

-

If a function is provided, it's called once when the first query is executed.

-

https://github.com/sidorares/node-mysql2#using-connection-pools

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/MysqlOkPacket.html b/docs/interfaces/MysqlOkPacket.html deleted file mode 100644 index 2a3c76a6c..000000000 --- a/docs/interfaces/MysqlOkPacket.html +++ /dev/null @@ -1,74 +0,0 @@ -MysqlOkPacket | kysely
-
- -
-
-
-
- -

Interface MysqlOkPacket

-
-

Hierarchy

-
    -
  • MysqlOkPacket
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
affectedRows: number
-
- -
insertId: number
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/MysqlPool.html b/docs/interfaces/MysqlPool.html deleted file mode 100644 index d2c8e20dd..000000000 --- a/docs/interfaces/MysqlPool.html +++ /dev/null @@ -1,120 +0,0 @@ -MysqlPool | kysely
-
- -
-
-
-
- -

Interface MysqlPool

-
-

This interface is the subset of mysql2 driver's Pool class that -kysely needs.

-

We don't use the type from mysql2 here to not have a dependency to it.

-

https://github.com/sidorares/node-mysql2#using-connection-pools

-
-
-

Hierarchy

-
    -
  • MysqlPool
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
    - -
  • -
    -

    Parameters

    -
      -
    • -
      callback: ((error: unknown) => void)
      -
        -
      • -
          -
        • (error: unknown): void
        • -
        • -
          -

          Parameters

          -
            -
          • -
            error: unknown
          -

          Returns void

    -

    Returns void

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/MysqlPoolConnection.html b/docs/interfaces/MysqlPoolConnection.html deleted file mode 100644 index aeb166d52..000000000 --- a/docs/interfaces/MysqlPoolConnection.html +++ /dev/null @@ -1,133 +0,0 @@ -MysqlPoolConnection | kysely
-
- -
-
-
-
- -

Interface MysqlPoolConnection

-
-

Hierarchy

-
    -
  • MysqlPoolConnection
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/MysqlStream.html b/docs/interfaces/MysqlStream.html deleted file mode 100644 index 174adab5b..000000000 --- a/docs/interfaces/MysqlStream.html +++ /dev/null @@ -1,75 +0,0 @@ -MysqlStream | kysely
-
- -
-
-
-
- -

Interface MysqlStream<T>

-
-

Type Parameters

-
    -
  • -

    T

-
-

Hierarchy

-
    -
  • MysqlStream
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/MysqlStreamOptions.html b/docs/interfaces/MysqlStreamOptions.html deleted file mode 100644 index 7f6b44f83..000000000 --- a/docs/interfaces/MysqlStreamOptions.html +++ /dev/null @@ -1,74 +0,0 @@ -MysqlStreamOptions | kysely
-
- -
-
-
-
- -

Interface MysqlStreamOptions

-
-

Hierarchy

-
    -
  • MysqlStreamOptions
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
highWaterMark?: number
-
- -
objectMode?: boolean
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/NoMigrations.html b/docs/interfaces/NoMigrations.html deleted file mode 100644 index 7b6d99a48..000000000 --- a/docs/interfaces/NoMigrations.html +++ /dev/null @@ -1,70 +0,0 @@ -NoMigrations | kysely
-
- -
-
-
-
- -

Interface NoMigrations

-
-

Type for the NO_MIGRATIONS constant. Never create one of these.

-
-
-

Hierarchy

-
    -
  • NoMigrations
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
__noMigrations__: true
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/OffsetNode.html b/docs/interfaces/OffsetNode.html deleted file mode 100644 index a7f6aa5bf..000000000 --- a/docs/interfaces/OffsetNode.html +++ /dev/null @@ -1,78 +0,0 @@ -OffsetNode | kysely
-
- -
-
-
-
- -

Interface OffsetNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "OffsetNode"
-
- -
offset: ValueNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/OnConflictBuilderProps.html b/docs/interfaces/OnConflictBuilderProps.html deleted file mode 100644 index 0dea72f3d..000000000 --- a/docs/interfaces/OnConflictBuilderProps.html +++ /dev/null @@ -1,67 +0,0 @@ -OnConflictBuilderProps | kysely
-
- -
-
-
-
- -

Interface OnConflictBuilderProps

-
-

Hierarchy

-
    -
  • OnConflictBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
onConflictNode: OnConflictNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/OnConflictNode.html b/docs/interfaces/OnConflictNode.html deleted file mode 100644 index 2511c2f58..000000000 --- a/docs/interfaces/OnConflictNode.html +++ /dev/null @@ -1,120 +0,0 @@ -OnConflictNode | kysely
-
- -
-
-
-
- -

Interface OnConflictNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
- -
columns?: readonly ColumnNode[]
-
- -
constraint?: IdentifierNode
-
- -
doNothing?: boolean
-
- -
indexExpression?: OperationNode
-
- -
indexWhere?: WhereNode
-
- -
kind: "OnConflictNode"
-
- -
updateWhere?: WhereNode
-
- -
updates?: readonly ColumnUpdateNode[]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/OnDuplicateKeyNode.html b/docs/interfaces/OnDuplicateKeyNode.html deleted file mode 100644 index 4b3226056..000000000 --- a/docs/interfaces/OnDuplicateKeyNode.html +++ /dev/null @@ -1,78 +0,0 @@ -OnDuplicateKeyNode | kysely
-
- -
-
-
-
- -

Interface OnDuplicateKeyNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "OnDuplicateKeyNode"
-
- -
updates: readonly ColumnUpdateNode[]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/OnNode.html b/docs/interfaces/OnNode.html deleted file mode 100644 index 230e879e6..000000000 --- a/docs/interfaces/OnNode.html +++ /dev/null @@ -1,78 +0,0 @@ -OnNode | kysely
-
- -
-
-
-
- -

Interface OnNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
kind -on -
-
-

Properties

-
- -
kind: "OnNode"
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/OperationNode.html b/docs/interfaces/OperationNode.html deleted file mode 100644 index 0132685f3..000000000 --- a/docs/interfaces/OperationNode.html +++ /dev/null @@ -1,146 +0,0 @@ -OperationNode | kysely
-
- -
-
-
-
- -

Interface OperationNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/OperationNodeSource.html b/docs/interfaces/OperationNodeSource.html deleted file mode 100644 index a1b98b04f..000000000 --- a/docs/interfaces/OperationNodeSource.html +++ /dev/null @@ -1,96 +0,0 @@ -OperationNodeSource | kysely
-
- -
- -
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/OperatorNode.html b/docs/interfaces/OperatorNode.html deleted file mode 100644 index ecd3dde09..000000000 --- a/docs/interfaces/OperatorNode.html +++ /dev/null @@ -1,78 +0,0 @@ -OperatorNode | kysely
-
- -
-
-
-
- -

Interface OperatorNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "OperatorNode"
-
- -
operator: "match" | "is" | "=" | "==" | "!=" | "<>" | ">" | ">=" | "<" | "<=" | "in" | "not in" | "is not" | "like" | "not like" | "ilike" | "not ilike" | "@>" | "<@" | "?" | "?&" | "!<" | "!>" | "<=>" | "!~" | "~" | "~*" | "!~*" | "@@" | "@@@" | "!!" | "<->" | "+" | "-" | "*" | "/" | "%" | "^" | "&" | "|" | "#" | "<<" | ">>" | "&&" | "||" | "exists" | "not exists" | "not"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/OrNode.html b/docs/interfaces/OrNode.html deleted file mode 100644 index 4c00623a2..000000000 --- a/docs/interfaces/OrNode.html +++ /dev/null @@ -1,85 +0,0 @@ -OrNode | kysely
-
- -
-
-
-
- -

Interface OrNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "OrNode"
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/OrderByItemNode.html b/docs/interfaces/OrderByItemNode.html deleted file mode 100644 index fa9efdadd..000000000 --- a/docs/interfaces/OrderByItemNode.html +++ /dev/null @@ -1,85 +0,0 @@ -OrderByItemNode | kysely
-
- -
-
-
-
- -

Interface OrderByItemNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
direction?: OperationNode
-
- -
kind: "OrderByItemNode"
-
- -
orderBy: OperationNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/OrderByNode.html b/docs/interfaces/OrderByNode.html deleted file mode 100644 index fe9c7e440..000000000 --- a/docs/interfaces/OrderByNode.html +++ /dev/null @@ -1,78 +0,0 @@ -OrderByNode | kysely
-
- -
-
-
-
- -

Interface OrderByNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
items: readonly OrderByItemNode[]
-
- -
kind: "OrderByNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/OverNode.html b/docs/interfaces/OverNode.html deleted file mode 100644 index d1f3da1da..000000000 --- a/docs/interfaces/OverNode.html +++ /dev/null @@ -1,85 +0,0 @@ -OverNode | kysely
-
- -
-
-
-
- -

Interface OverNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "OverNode"
-
- -
orderBy?: OrderByNode
-
- -
partitionBy?: PartitionByNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ParensNode.html b/docs/interfaces/ParensNode.html deleted file mode 100644 index 94758da40..000000000 --- a/docs/interfaces/ParensNode.html +++ /dev/null @@ -1,78 +0,0 @@ -ParensNode | kysely
-
- -
-
-
-
- -

Interface ParensNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "ParensNode"
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/PartitionByItemNode.html b/docs/interfaces/PartitionByItemNode.html deleted file mode 100644 index 8bf464456..000000000 --- a/docs/interfaces/PartitionByItemNode.html +++ /dev/null @@ -1,78 +0,0 @@ -PartitionByItemNode | kysely
-
- -
-
-
-
- -

Interface PartitionByItemNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "PartitionByItemNode"
-
- -
partitionBy: SimpleReferenceExpressionNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/PartitionByNode.html b/docs/interfaces/PartitionByNode.html deleted file mode 100644 index 7ec785914..000000000 --- a/docs/interfaces/PartitionByNode.html +++ /dev/null @@ -1,78 +0,0 @@ -PartitionByNode | kysely
-
- -
-
-
-
- -

Interface PartitionByNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
items: readonly PartitionByItemNode[]
-
- -
kind: "PartitionByNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/PluginTransformQueryArgs.html b/docs/interfaces/PluginTransformQueryArgs.html deleted file mode 100644 index c11877bf7..000000000 --- a/docs/interfaces/PluginTransformQueryArgs.html +++ /dev/null @@ -1,74 +0,0 @@ -PluginTransformQueryArgs | kysely
-
- -
-
-
-
- -

Interface PluginTransformQueryArgs

-
-

Hierarchy

-
    -
  • PluginTransformQueryArgs
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
-
- -
queryId: QueryId
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/PluginTransformResultArgs.html b/docs/interfaces/PluginTransformResultArgs.html deleted file mode 100644 index 0a450bec2..000000000 --- a/docs/interfaces/PluginTransformResultArgs.html +++ /dev/null @@ -1,74 +0,0 @@ -PluginTransformResultArgs | kysely
-
- -
-
-
-
- -

Interface PluginTransformResultArgs

-
-

Hierarchy

-
    -
  • PluginTransformResultArgs
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
queryId: QueryId
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/PostgresCursor.html b/docs/interfaces/PostgresCursor.html deleted file mode 100644 index 9ad8c5c74..000000000 --- a/docs/interfaces/PostgresCursor.html +++ /dev/null @@ -1,90 +0,0 @@ -PostgresCursor | kysely
-
- -
-
-
-
- -

Interface PostgresCursor<T>

-
-

Type Parameters

-
    -
  • -

    T

-
-

Hierarchy

-
    -
  • PostgresCursor
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/PostgresDialectConfig.html b/docs/interfaces/PostgresDialectConfig.html deleted file mode 100644 index 753e950c3..000000000 --- a/docs/interfaces/PostgresDialectConfig.html +++ /dev/null @@ -1,107 +0,0 @@ -PostgresDialectConfig | kysely
-
- -
-
-
-
- -

Interface PostgresDialectConfig

-
-

Config for the PostgreSQL dialect.

-
-
-

Hierarchy

-
    -
  • PostgresDialectConfig
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- - -

https://github.com/brianc/node-postgres/tree/master/packages/pg-cursor

-
import Cursor from 'pg-cursor'
// or
import * as Cursor from 'pg-cursor'

new PostgresDialect({
cursor: Cursor
}) -
-
-
- -
onCreateConnection?: ((connection: DatabaseConnection) => Promise<void>)
-
-

Type declaration

-
-
- -
pool: PostgresPool | (() => Promise<PostgresPool>)
-

A postgres Pool instance or a function that returns one.

-

If a function is provided, it's called once when the first query is executed.

-

https://node-postgres.com/api/pool

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/PostgresPool.html b/docs/interfaces/PostgresPool.html deleted file mode 100644 index d4090e8dc..000000000 --- a/docs/interfaces/PostgresPool.html +++ /dev/null @@ -1,86 +0,0 @@ -PostgresPool | kysely
-
- -
-
-
-
- -

Interface PostgresPool

-
-

This interface is the subset of pg driver's Pool class that -kysely needs.

-

We don't use the type from pg here to not have a dependency to it.

-

https://node-postgres.com/api/pool

-
-
-

Hierarchy

-
    -
  • PostgresPool
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/PostgresPoolClient.html b/docs/interfaces/PostgresPoolClient.html deleted file mode 100644 index f5638948f..000000000 --- a/docs/interfaces/PostgresPoolClient.html +++ /dev/null @@ -1,107 +0,0 @@ -PostgresPoolClient | kysely
-
- -
-
-
-
- -

Interface PostgresPoolClient

-
-

Hierarchy

-
    -
  • PostgresPoolClient
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/PostgresQueryResult.html b/docs/interfaces/PostgresQueryResult.html deleted file mode 100644 index 57f17ecdb..000000000 --- a/docs/interfaces/PostgresQueryResult.html +++ /dev/null @@ -1,86 +0,0 @@ -PostgresQueryResult | kysely
-
- -
-
-
-
- -

Interface PostgresQueryResult<R>

-
-

Type Parameters

-
    -
  • -

    R

-
-

Hierarchy

-
    -
  • PostgresQueryResult
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
command: "UPDATE" | "DELETE" | "INSERT" | "SELECT"
-
- -
rowCount: number
-
- -
rows: R[]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/PostgresStream.html b/docs/interfaces/PostgresStream.html deleted file mode 100644 index 15bb161a8..000000000 --- a/docs/interfaces/PostgresStream.html +++ /dev/null @@ -1,75 +0,0 @@ -PostgresStream | kysely
-
- -
-
-
-
- -

Interface PostgresStream<T>

-
-

Type Parameters

-
    -
  • -

    T

-
-

Hierarchy

-
    -
  • PostgresStream
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/PrimaryKeyConstraintNode.html b/docs/interfaces/PrimaryKeyConstraintNode.html deleted file mode 100644 index 9df53987a..000000000 --- a/docs/interfaces/PrimaryKeyConstraintNode.html +++ /dev/null @@ -1,84 +0,0 @@ -PrimaryKeyConstraintNode | kysely
-
- -
-
-
-
- -

Interface PrimaryKeyConstraintNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
columns: readonly ColumnNode[]
-
- -
kind: "PrimaryKeyConstraintNode"
-
- -
name?: IdentifierNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/PrimitiveValueListNode.html b/docs/interfaces/PrimitiveValueListNode.html deleted file mode 100644 index 21a3c2487..000000000 --- a/docs/interfaces/PrimitiveValueListNode.html +++ /dev/null @@ -1,83 +0,0 @@ -PrimitiveValueListNode | kysely
-
- -
-
-
-
- -

Interface PrimitiveValueListNode

-
-

This node is basically just a performance optimization over the normal ValueListNode. -The queries often contain large arrays of primitive values (for example in a where in list) -and we don't want to create a ValueNode for each item in those lists.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "PrimitiveValueListNode"
-
- -
values: readonly unknown[]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/QueryCompiler.html b/docs/interfaces/QueryCompiler.html deleted file mode 100644 index 3102e7776..000000000 --- a/docs/interfaces/QueryCompiler.html +++ /dev/null @@ -1,82 +0,0 @@ -QueryCompiler | kysely
-
- -
-
-
-
- -

Interface QueryCompiler

-
-

a QueryCompiler compiles a query expressed as a tree of OperationNodes into SQL.

-
-
-

Hierarchy

-
    -
  • QueryCompiler
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/QueryCreatorProps.html b/docs/interfaces/QueryCreatorProps.html deleted file mode 100644 index 8d0fcdde7..000000000 --- a/docs/interfaces/QueryCreatorProps.html +++ /dev/null @@ -1,74 +0,0 @@ -QueryCreatorProps | kysely
-
- -
-
-
-
- -

Interface QueryCreatorProps

-
-

Hierarchy

-
    -
  • QueryCreatorProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
withNode?: WithNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/QueryExecutor.html b/docs/interfaces/QueryExecutor.html deleted file mode 100644 index 61ee10387..000000000 --- a/docs/interfaces/QueryExecutor.html +++ /dev/null @@ -1,323 +0,0 @@ -QueryExecutor | kysely
-
- -
-
-
-
- -

Interface QueryExecutor

-
-

This interface abstracts away the details of how to compile a query into SQL -and execute it. Instead of passing around all those details, SelectQueryBuilder -and other classes that execute queries can just pass around and instance of -QueryExecutor.

-
-
-

Hierarchy

-
-
-
-
- -
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Executes a compiled query and runs the result through all plugins' -transformResult method. Results are streamead instead of loaded -at once.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      R

    -
    -

    Parameters

    -
      -
    • -
      compiledQuery: CompiledQuery<R>
    • -
    • -
      chunkSize: number
      -

      How many rows should be pulled from the database at once. Supported -only by the postgres driver.

      -
    • -
    • -
      queryId: QueryId
    -

    Returns AsyncIterableIterator<QueryResult<R>>

-
- -
    - -
  • -

    Given the query the user has built (expressed as an operation node tree) -this method runs it through all plugins' transformQuery methods and -returns the result.

    -
    -
    -

    Type Parameters

    -
    -
    -

    Parameters

    -
      -
    • -
      node: T
    • -
    • -
      queryId: QueryId
    -

    Returns T

-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/QueryLogEvent.html b/docs/interfaces/QueryLogEvent.html deleted file mode 100644 index 9b690b98c..000000000 --- a/docs/interfaces/QueryLogEvent.html +++ /dev/null @@ -1,81 +0,0 @@ -QueryLogEvent | kysely
-
- -
-
-
-
- -

Interface QueryLogEvent

-
-

Hierarchy

-
    -
  • QueryLogEvent
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
level: "query"
-
- -
query: CompiledQuery<unknown>
-
- -
queryDurationMillis: number
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/QueryResult.html b/docs/interfaces/QueryResult.html deleted file mode 100644 index 2649f0201..000000000 --- a/docs/interfaces/QueryResult.html +++ /dev/null @@ -1,105 +0,0 @@ -QueryResult | kysely
-
- -
-
-
-
- -

Interface QueryResult<O>

-
-

Type Parameters

-
    -
  • -

    O

-
-

Hierarchy

-
    -
  • QueryResult
-
-
-
- -
-
-

Properties

-
- -
insertId?: bigint
-

This is defined for insert queries on dialects that return -the auto incrementing primary key from an insert.

-
-
- -
numAffectedRows?: bigint
-

This is defined for insert, update and delete queries and contains -the number of rows the query inserted/updated/deleted.

-
-
- -
numUpdatedOrDeletedRows?: bigint
-
-

Deprecated

use numAffectedRows instead.

-
-
- -
rows: O[]
-

The rows returned by the query. This is always defined and is -empty if the query returned no rows.

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/RawBuilderProps.html b/docs/interfaces/RawBuilderProps.html deleted file mode 100644 index b22875cfc..000000000 --- a/docs/interfaces/RawBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -RawBuilderProps | kysely
-
- -
-
-
-
- -

Interface RawBuilderProps

-
-

Hierarchy

-
    -
  • RawBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
plugins?: readonly KyselyPlugin[]
-
- -
queryId: QueryId
-
- -
rawNode: RawNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/RawNode.html b/docs/interfaces/RawNode.html deleted file mode 100644 index 43ce314db..000000000 --- a/docs/interfaces/RawNode.html +++ /dev/null @@ -1,85 +0,0 @@ -RawNode | kysely
-
- -
-
-
-
- -

Interface RawNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "RawNode"
-
- -
parameters: readonly OperationNode[]
-
- -
sqlFragments: readonly string[]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ReferenceNode.html b/docs/interfaces/ReferenceNode.html deleted file mode 100644 index f1416302f..000000000 --- a/docs/interfaces/ReferenceNode.html +++ /dev/null @@ -1,85 +0,0 @@ -ReferenceNode | kysely
-
- -
-
-
-
- -

Interface ReferenceNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
column: ColumnNode | SelectAllNode
-
- -
kind: "ReferenceNode"
-
- -
table: TableNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ReferencesNode.html b/docs/interfaces/ReferencesNode.html deleted file mode 100644 index a5a162437..000000000 --- a/docs/interfaces/ReferencesNode.html +++ /dev/null @@ -1,99 +0,0 @@ -ReferencesNode | kysely
-
- -
-
-
-
- -

Interface ReferencesNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
columns: readonly ColumnNode[]
-
- -
kind: "ReferencesNode"
-
- -
onDelete?: "no action" | "restrict" | "cascade" | "set null" | "set default"
-
- -
onUpdate?: "no action" | "restrict" | "cascade" | "set null" | "set default"
-
- -
table: TableNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/RenameColumnNode.html b/docs/interfaces/RenameColumnNode.html deleted file mode 100644 index b10f69ae0..000000000 --- a/docs/interfaces/RenameColumnNode.html +++ /dev/null @@ -1,85 +0,0 @@ -RenameColumnNode | kysely
-
- -
-
-
-
- -

Interface RenameColumnNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
column: ColumnNode
-
- -
kind: "RenameColumnNode"
-
- -
renameTo: ColumnNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ReturningInterface.html b/docs/interfaces/ReturningInterface.html deleted file mode 100644 index 18b7da4ab..000000000 --- a/docs/interfaces/ReturningInterface.html +++ /dev/null @@ -1,144 +0,0 @@ -ReturningInterface | kysely
-
- -
-
-
-
- -

Interface ReturningInterface<DB, TB, O>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    O

-
-

Hierarchy

-
    -
  • ReturningInterface
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
    - -
  • -

    Allows you to return data from modified rows.

    -

    On supported databases like PostgreSQL, this method can be chained to -insert, update and delete queries to return data.

    -

    Note that on SQLite you need to give aliases for the expressions to avoid -this bug in SQLite. -For example .returning('id as id').

    -

    Also see the returningAll method.

    - - -

    Examples

    -
    -

    Return one column:

    -
    const { id } = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .returning('id')
    .executeTakeFirst() -
    -

    Return multiple columns:

    -
    const { id, first_name } = await db
    .insertInto('person')
    .values({
    first_name: 'Jennifer',
    last_name: 'Aniston'
    })
    .returning(['id', 'last_name'])
    .executeTakeFirst() -
    -

    Return arbitrary expressions:

    -
    importsql } 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('pets').select('pet.id').limit(1).as('first_pet_id')
    ])
    .executeTakeFirst() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      SE extends string | AliasedExpression<any, any> | DynamicReferenceBuilder<any> | AliasedExpressionFactory<DB, TB>

    -
    -

    Parameters

    -
      -
    • -
      selections: readonly SE[]
    -

    Returns ReturningInterface<DB, TB, ReturningRow<DB, TB, O, SE>>

  • - -
  • -
    -

    Type Parameters

    -
      -
    • -

      SE extends string | AliasedExpression<any, any> | DynamicReferenceBuilder<any> | AliasedExpressionFactory<DB, TB>

    -
    -

    Parameters

    -
      -
    • -
      selection: SE
    -

    Returns ReturningInterface<DB, TB, ReturningRow<DB, TB, O, SE>>

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ReturningNode.html b/docs/interfaces/ReturningNode.html deleted file mode 100644 index 2932bed88..000000000 --- a/docs/interfaces/ReturningNode.html +++ /dev/null @@ -1,78 +0,0 @@ -ReturningNode | kysely
-
- -
-
-
-
- -

Interface ReturningNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "ReturningNode"
-
- -
selections: readonly SelectionNode[]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/SchemaMetadata.html b/docs/interfaces/SchemaMetadata.html deleted file mode 100644 index 91e95b9c4..000000000 --- a/docs/interfaces/SchemaMetadata.html +++ /dev/null @@ -1,67 +0,0 @@ -SchemaMetadata | kysely
-
- -
-
-
-
- -

Interface SchemaMetadata

-
-

Hierarchy

-
    -
  • SchemaMetadata
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
name: string
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/SelectAllNode.html b/docs/interfaces/SelectAllNode.html deleted file mode 100644 index 7eec4651e..000000000 --- a/docs/interfaces/SelectAllNode.html +++ /dev/null @@ -1,71 +0,0 @@ -SelectAllNode | kysely
-
- -
-
-
-
- -

Interface SelectAllNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "SelectAllNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/SelectQueryBuilderProps.html b/docs/interfaces/SelectQueryBuilderProps.html deleted file mode 100644 index 4262b2a79..000000000 --- a/docs/interfaces/SelectQueryBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -SelectQueryBuilderProps | kysely
-
- -
-
-
-
- -

Interface SelectQueryBuilderProps

-
-

Hierarchy

-
    -
  • SelectQueryBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
queryId: QueryId
-
- -
queryNode: SelectQueryNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/SelectQueryNode.html b/docs/interfaces/SelectQueryNode.html deleted file mode 100644 index 380649e27..000000000 --- a/docs/interfaces/SelectQueryNode.html +++ /dev/null @@ -1,176 +0,0 @@ -SelectQueryNode | kysely
-
- -
-
-
-
- -

Interface SelectQueryNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
- -
distinctOn?: readonly OperationNode[]
-
- -
endModifiers?: readonly SelectModifierNode[]
-
- -
explain?: ExplainNode
-
- -
from: FromNode
-
- -
frontModifiers?: readonly SelectModifierNode[]
-
- -
groupBy?: GroupByNode
-
- -
having?: HavingNode
-
- -
joins?: readonly JoinNode[]
-
- -
kind: "SelectQueryNode"
-
- -
limit?: LimitNode
-
- -
offset?: OffsetNode
-
- -
orderBy?: OrderByNode
-
- -
selections?: readonly SelectionNode[]
-
- -
setOperations?: readonly SetOperationNode[]
-
- -
where?: WhereNode
-
- -
with?: WithNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/SelectionNode.html b/docs/interfaces/SelectionNode.html deleted file mode 100644 index df1cca248..000000000 --- a/docs/interfaces/SelectionNode.html +++ /dev/null @@ -1,78 +0,0 @@ -SelectionNode | kysely
-
- -
-
-
-
- -

Interface SelectionNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "SelectionNode"
-
- -
selection: SelectionNodeChild
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/SetOperationNode.html b/docs/interfaces/SetOperationNode.html deleted file mode 100644 index dd8c51524..000000000 --- a/docs/interfaces/SetOperationNode.html +++ /dev/null @@ -1,92 +0,0 @@ -SetOperationNode | kysely
-
- -
-
-
-
- -

Interface SetOperationNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
all: boolean
-
- -
expression: OperationNode
-
- -
kind: "SetOperationNode"
-
- -
operator: SetOperator
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/Sql.html b/docs/interfaces/Sql.html deleted file mode 100644 index 42c533e10..000000000 --- a/docs/interfaces/Sql.html +++ /dev/null @@ -1,401 +0,0 @@ -Sql | kysely
-
- -
-
-
-
- -

Interface Sql

-
-

Hierarchy

-
    -
  • Sql
-
-
    - -
  • -

    Template tag for creating raw SQL snippets and queries.

    -
    import { sql } from 'kysely'

    const id = 123
    const snippet = sql<Person[]>`select * from person where id = ${id}` -
    -

    Substitutions (the things inside ${}) are automatically passed to the database -as parameters and are never interpolated to the SQL string. There's no need to worry -about SQL injection vulnerabilities. Substitutions can be values, other sql -expressions, queries and almost anything else Kysely can produce and they get -handled correctly. See the examples below.

    -

    If you need your substitutions to be interpreted as identifiers, value literals or -lists of things, see the ref, table, id, -lit, raw and join functions.

    -

    You can pass sql snippets returned by the sql tag pretty much anywhere. Whenever -something can't be done using the Kysely API, you should be able to drop down to -raw SQL using the sql tag. Here's an example query that uses raw sql in a bunch -of methods:

    -
    const persons = await db
    .selectFrom('person')
    .select(
    // If you use `sql` in a select statement, remember to call the `as`
    // method to give it an alias.
    sql<string>`concat(first_name, ' ', last_name)`.as('full_name')
    )
    .where(sql`birthdate between ${date1} and ${date2}`)
    // Here we assume we have list of nicknames for the person
    // (a list of strings) and we use the PostgreSQL `@>` operator
    // to test if all of them are valid nicknames for the user.
    .where('nicknames', '@>', sql`ARRAY[${sql.join(nicknames)}]`)
    .orderBy(sql`concat(first_name, ' ', last_name)`)
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select concat(first_name, ' ', last_name) as "full_name"
    from "person"
    where birthdate between $1 and $2
    and "nicknames" @> ARRAY[$3, $4, $5, $6, $7, $8, $9, $10]
    order by concat(first_name, ' ', last_name) -
    -

    SQL snippets can be executed by calling the execute method and passing a Kysely -instance as the only argument:

    -
    const result = await sql<Person[]>`select * from person`.execute(db)
    -
    -

    You can merge other sql expressions and queries using substitutions:

    -
    const petName = db.selectFrom('pet').select('name').limit(1)
    const fullName = sql`concat(first_name, ' ', last_name)`

    sql`
    select ${fullName} as full_name, ${petName} as pet_name
    from person
    ` -
    -

    Substitutions also handle ref, -ref and pretty much anything else you -throw at it. Here's an example of calling a function in a -type-safe way:

    -
    db.selectFrom('person')
    .select([
    'first_name',
    'last_name',
    (eb) => {
    // The `eb.ref` method is type-safe and only accepts
    // column references that are possible.
    const firstName = eb.ref('first_name')
    const lastName = eb.ref('last_name')

    const fullName = sql<string>`concat(${firstName}, ' ', ${lastName})`
    return fullName.as('full_name')
    }
    ]) -
    -

    don't know if that amount of ceremony is worth the small increase in -type-safety though... But it's possible.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      T = unknown

    -
    -

    Parameters

    -
      -
    • -
      sqlFragments: TemplateStringsArray
    • -
    • -
      Rest ...parameters: unknown[]
    -

    Returns RawBuilder<T>

-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
    - -
  • -

    This can be used to add arbitrary identifiers to SQL snippets.

    -

    Does the same thing as ref and table -but can also be used for any other identifiers like index names.

    -

    You should use ref and table -instead of this whenever possible as they produce a more sematic -operation node tree.

    -

    WARNING! Using this with unchecked inputs WILL lead to SQL injection -vulnerabilities. The input is not checked or escaped by Kysely in any way.

    -
    const indexName = 'person_first_name_index'

    sql`create index ${indexName} on person` -
    -

    The generated SQL (PostgreSQL):

    -
    create index "person_first_name_index" on person
    -
    -

    Multiple identifiers get separated by dots:

    -
    const schema = 'public'
    const columnName = 'first_name'
    const table = 'person'

    sql`select ${sql.id(schema, table, columnName)}} from ${sql.id(schema, table)}` -
    -

    The generated SQL (PostgreSQL):

    -
    select "public"."person"."first_name" from "public"."person"
    -
    -
    -
    -

    Parameters

    -
      -
    • -
      Rest ...ids: readonly string[]
    -

    Returns RawBuilder<unknown>

-
- -
    - -
  • -

    This can be used to add lists of things to SQL snippets.

    - - -

    Examples

    -
    -
    function findByNicknames(nicknames: string[]): Promise<Person[]> {
    return db
    .selectFrom('person')
    .selectAll()
    .where('nicknames', '@>', sql`ARRAY[${sql.join(nicknames)}]`)
    .execute()
    } -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "person"
    where "nicknames" @> ARRAY[$1, $2, $3, $4, $5, $6, $7, $8] -
    -

    The second argument is the joining SQL expression that defaults -to

    -
    sql`, `
    -
    -

    In addition to values, items in the list can be also sql -expressions, queries or anything else the normal substitutions -support:

    -
    const things = [
    123,
    sql`(1 == 1)`,
    db.selectFrom('person').selectAll(),
    sql.lit(false),
    sql.id('first_name')
    ]

    sql`BEFORE ${sql.join(things, sql`::varchar, `)} AFTER` -
    -

    The generated SQL (PostgreSQL):

    -
    BEFORE $1::varchar, (1 == 1)::varchar, (select * from "person")::varchar, false::varchar, "first_name" AFTER
    -
    -
    -
    -

    Parameters

    -
      -
    • -
      array: readonly unknown[]
    • -
    • -
      Optional separator: RawBuilder<any>
    -

    Returns RawBuilder<unknown>

-
- -
    - -
  • -

    This can be used to add literal values to SQL snippets.

    -

    WARNING! Using this with unchecked inputs WILL lead to SQL injection -vulnerabilities. The input is not checked or escaped by Kysely in any way. -You almost always want to use normal substitutions that get sent to the -db as parameters.

    -
    const firstName = 'first_name'

    sql`select * from person where first_name = ${sql.lit(firstName)}` -
    -

    The generated SQL (PostgreSQL):

    -
    select * from person where first_name = 'first_name'
    -
    -

    As you can see from the example above, the value was added directly to -the SQL string instead of as a parameter. Only use this function when -something can't be sent as a parameter.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      V

    -
    -

    Parameters

    -
      -
    • -
      value: V
    -

    Returns RawBuilder<V>

-
- -
-
- -
    - -
  • -

    This can be used to add arbitrary runtime SQL to SQL snippets.

    -

    WARNING! Using this with unchecked inputs WILL lead to SQL injection -vulnerabilities. The input is not checked or escaped by Kysely in any way.

    -
    const firstName = "'first_name'"

    sql`select * from person where first_name = ${sql.raw(firstName)}` -
    -

    The generated SQL (PostgreSQL):

    -
    select * from person where first_name = 'first_name'
    -
    -

    Note that the difference to sql.lit is that this function -doesn't assume the inputs are values. The input to this function -can be any sql and it's simply glued to the parent string as-is.

    -
    -
    -

    Type Parameters

    -
      -
    • -

      R = unknown

    -
    -

    Parameters

    -
      -
    • -
      anySql: string
    -

    Returns RawBuilder<R>

-
- -
    - -
  • -

    This can be used to add runtime column references to SQL snippets.

    -

    By default ${} substitutions in sql template strings get -transformed into parameters. You can use this function to tell -Kysely to interpret them as column references instead.

    -

    WARNING! Using this with unchecked inputs WILL lead to SQL injection -vulnerabilities. The input is not checked or escaped by Kysely in any way.

    -
    const columnRef = 'first_name'

    sql`select ${sql.ref(columnRef)} from person` -
    -

    The generated SQL (PostgreSQL):

    -
    select "first_name" from person
    -
    -

    The refefences can also include a table name:

    -
    const columnRef = 'person.first_name'

    sql`select ${sql.ref(columnRef)}} from person` -
    -

    The generated SQL (PostgreSQL):

    -
    select "person"."first_name" from person
    -
    -

    The refefences can also include a schema on supported databases:

    -
    const columnRef = 'public.person.first_name'

    sql`select ${sql.ref(columnRef)}} from person` -
    -

    The generated SQL (PostgreSQL):

    -
    select "public"."person"."first_name" from person
    -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      R = unknown

    -
    -

    Parameters

    -
      -
    • -
      columnReference: string
    -

    Returns RawBuilder<R>

-
- -
    - -
  • -

    This can be used to add runtime table references to SQL snippets.

    -

    By default ${} substitutions in sql template strings get -transformed into parameters. You can use this function to tell -Kysely to interpret them as table references instead.

    -

    WARNING! Using this with unchecked inputs WILL lead to SQL injection -vulnerabilities. The input is not checked or escaped by Kysely in any way.

    -
    const table = 'person'

    sql`select first_name from ${sql.table(table)}` -
    -

    The generated SQL (PostgreSQL):

    -
    select first_name from "person"
    -
    -

    The refefences can also include a schema on supported databases:

    -
    const table = 'public.person'

    sql`select first_name from ${sql.table(table)}` -
    -

    The generated SQL (PostgreSQL):

    -
    select first_name from "public"."person"
    -
    -
    -
    -

    Parameters

    -
      -
    • -
      tableReference: string
    -

    Returns RawBuilder<unknown>

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/SqliteDatabase.html b/docs/interfaces/SqliteDatabase.html deleted file mode 100644 index 58a7be4ab..000000000 --- a/docs/interfaces/SqliteDatabase.html +++ /dev/null @@ -1,91 +0,0 @@ -SqliteDatabase | kysely
-
- -
-
-
-
- -

Interface SqliteDatabase

-
-

This interface is the subset of better-sqlite3 driver's Database class that -kysely needs.

-

We don't use the type from better-sqlite3 here to not have a dependency to it.

-

https://github.com/JoshuaWise/better-sqlite3/blob/master/docs/api.md#new-databasepath-options

-
-
-

Hierarchy

-
    -
  • SqliteDatabase
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/SqliteDialectConfig.html b/docs/interfaces/SqliteDialectConfig.html deleted file mode 100644 index 040a32b30..000000000 --- a/docs/interfaces/SqliteDialectConfig.html +++ /dev/null @@ -1,97 +0,0 @@ -SqliteDialectConfig | kysely
-
- -
-
-
-
- -

Interface SqliteDialectConfig

-
-

Config for the SQLite dialect.

-
-
-

Hierarchy

-
    -
  • SqliteDialectConfig
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
database: SqliteDatabase | (() => Promise<SqliteDatabase>)
-

An sqlite Database instance or a function that returns one.

-

If a function is provided, it's called once when the first query is executed.

-

https://github.com/JoshuaWise/better-sqlite3/blob/master/docs/api.md#new-databasepath-options

-
-
- -
onCreateConnection?: ((connection: DatabaseConnection) => Promise<void>)
-
-

Type declaration

-
    -
  • -
      -
    • (connection: DatabaseConnection): Promise<void>
    • -
    • -

      Called once when the first query is executed.

      -

      This is a Kysely specific feature and does not come from the better-sqlite3 module.

      -
      -
      -

      Parameters

      -
      -

      Returns Promise<void>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/SqliteStatement.html b/docs/interfaces/SqliteStatement.html deleted file mode 100644 index d57191627..000000000 --- a/docs/interfaces/SqliteStatement.html +++ /dev/null @@ -1,107 +0,0 @@ -SqliteStatement | kysely
-
- -
-
-
-
- -

Interface SqliteStatement

-
-

Hierarchy

-
    -
  • SqliteStatement
-
-
-
- -
-
-

Properties

-
-
-

Methods

-
all -run -
-
-

Properties

-
- -
reader: boolean
-
-

Methods

-
- -
-
- -
    - -
  • -
    -

    Parameters

    -
      -
    • -
      parameters: readonly unknown[]
    -

    Returns {
        changes: number | bigint;
        lastInsertRowid: number | bigint;
    }

    -
      -
    • -
      changes: number | bigint
    • -
    • -
      lastInsertRowid: number | bigint
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/Streamable.html b/docs/interfaces/Streamable.html deleted file mode 100644 index 72a30cef5..000000000 --- a/docs/interfaces/Streamable.html +++ /dev/null @@ -1,97 +0,0 @@ -Streamable | kysely
-
- -
-
-
-
- -

Interface Streamable<O>

-
-

Type Parameters

-
    -
  • -

    O

-
-

Hierarchy

-
    -
  • Streamable
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
-
-

Methods

-
- -
    - -
  • -

    Executes the query and streams the rows.

    -

    The optional argument chunkSize defines how many rows to fetch from the database -at a time. It only affects some dialects like PostgreSQL that support it.

    - - -

    Examples

    -
    -
    const stream = db.
    .selectFrom('person')
    .select(['first_name', 'last_name'])
    .where('gender', '=', 'other')
    .stream()

    for await (const person of stream) {
    console.log(person.first_name)

    if (person.last_name === 'Something') {
    // Breaking or returning before the stream has ended will release
    // the database connection and invalidate the stream.
    break
    }
    } -
    -
    -
    -

    Parameters

    -
      -
    • -
      Optional chunkSize: number
    -

    Returns AsyncIterableIterator<O>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/TableMetadata.html b/docs/interfaces/TableMetadata.html deleted file mode 100644 index 7981ad3ca..000000000 --- a/docs/interfaces/TableMetadata.html +++ /dev/null @@ -1,88 +0,0 @@ -TableMetadata | kysely
-
- -
-
-
-
- -

Interface TableMetadata

-
-

Hierarchy

-
    -
  • TableMetadata
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
columns: ColumnMetadata[]
-
- -
isView: boolean
-
- -
name: string
-
- -
schema?: string
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/TableNode.html b/docs/interfaces/TableNode.html deleted file mode 100644 index c5675a807..000000000 --- a/docs/interfaces/TableNode.html +++ /dev/null @@ -1,78 +0,0 @@ -TableNode | kysely
-
- -
-
-
-
- -

Interface TableNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "TableNode"
-
- -
table: SchemableIdentifierNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/TransactionSettings.html b/docs/interfaces/TransactionSettings.html deleted file mode 100644 index fc278ba3c..000000000 --- a/docs/interfaces/TransactionSettings.html +++ /dev/null @@ -1,67 +0,0 @@ -TransactionSettings | kysely
-
- -
-
-
-
- -

Interface TransactionSettings

-
-

Hierarchy

-
    -
  • TransactionSettings
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
isolationLevel?: "read uncommitted" | "read committed" | "repeatable read" | "serializable"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/UnaryOperationNode.html b/docs/interfaces/UnaryOperationNode.html deleted file mode 100644 index 152a183b5..000000000 --- a/docs/interfaces/UnaryOperationNode.html +++ /dev/null @@ -1,85 +0,0 @@ -UnaryOperationNode | kysely
-
- -
-
-
-
- -

Interface UnaryOperationNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "UnaryOperationNode"
-
- -
operand: OperationNode
-
- -
operator: OperationNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/UniqueConstraintNode.html b/docs/interfaces/UniqueConstraintNode.html deleted file mode 100644 index 62c8917ef..000000000 --- a/docs/interfaces/UniqueConstraintNode.html +++ /dev/null @@ -1,85 +0,0 @@ -UniqueConstraintNode | kysely
-
- -
-
-
-
- -

Interface UniqueConstraintNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
columns: readonly ColumnNode[]
-
- -
kind: "UniqueConstraintNode"
-
- -
name?: IdentifierNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/UpdateQueryBuilderProps.html b/docs/interfaces/UpdateQueryBuilderProps.html deleted file mode 100644 index a9dce2c4a..000000000 --- a/docs/interfaces/UpdateQueryBuilderProps.html +++ /dev/null @@ -1,81 +0,0 @@ -UpdateQueryBuilderProps | kysely
-
- -
-
-
-
- -

Interface UpdateQueryBuilderProps

-
-

Hierarchy

-
    -
  • UpdateQueryBuilderProps
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
executor: QueryExecutor
-
- -
queryId: QueryId
-
- -
queryNode: UpdateQueryNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/UpdateQueryNode.html b/docs/interfaces/UpdateQueryNode.html deleted file mode 100644 index d6c47ffd3..000000000 --- a/docs/interfaces/UpdateQueryNode.html +++ /dev/null @@ -1,127 +0,0 @@ -UpdateQueryNode | kysely
-
- -
-
-
-
- -

Interface UpdateQueryNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
- -
explain?: ExplainNode
-
- -
from?: FromNode
-
- -
joins?: readonly JoinNode[]
-
- -
kind: "UpdateQueryNode"
-
- -
returning?: ReturningNode
-
- -
-
- -
updates?: readonly ColumnUpdateNode[]
-
- -
where?: WhereNode
-
- -
with?: WithNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/UsingNode.html b/docs/interfaces/UsingNode.html deleted file mode 100644 index ba9bcf94e..000000000 --- a/docs/interfaces/UsingNode.html +++ /dev/null @@ -1,78 +0,0 @@ -UsingNode | kysely
-
- -
-
-
-
- -

Interface UsingNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "UsingNode"
-
- -
tables: readonly OperationNode[]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ValueListNode.html b/docs/interfaces/ValueListNode.html deleted file mode 100644 index fdb97658d..000000000 --- a/docs/interfaces/ValueListNode.html +++ /dev/null @@ -1,78 +0,0 @@ -ValueListNode | kysely
-
- -
-
-
-
- -

Interface ValueListNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "ValueListNode"
-
- -
values: readonly OperationNode[]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ValueNode.html b/docs/interfaces/ValueNode.html deleted file mode 100644 index 480172175..000000000 --- a/docs/interfaces/ValueNode.html +++ /dev/null @@ -1,85 +0,0 @@ -ValueNode | kysely
-
- -
-
-
-
- -

Interface ValueNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
immediate?: boolean
-
- -
kind: "ValueNode"
-
- -
value: unknown
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/ValuesNode.html b/docs/interfaces/ValuesNode.html deleted file mode 100644 index 611abe56a..000000000 --- a/docs/interfaces/ValuesNode.html +++ /dev/null @@ -1,78 +0,0 @@ -ValuesNode | kysely
-
- -
-
-
-
- -

Interface ValuesNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "ValuesNode"
-
- -
values: readonly ValuesItemNode[]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/WhenNode.html b/docs/interfaces/WhenNode.html deleted file mode 100644 index 2a62e8dc5..000000000 --- a/docs/interfaces/WhenNode.html +++ /dev/null @@ -1,85 +0,0 @@ -WhenNode | kysely
-
- -
-
-
-
- -

Interface WhenNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
condition: OperationNode
-
- -
kind: "WhenNode"
-
- -
result?: OperationNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/WhereInterface.html b/docs/interfaces/WhereInterface.html deleted file mode 100644 index b07126efc..000000000 --- a/docs/interfaces/WhereInterface.html +++ /dev/null @@ -1,393 +0,0 @@ -WhereInterface | kysely
-
- -
-
-
-
- -

Interface WhereInterface<DB, TB>

-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-

Hierarchy

-
    -
  • WhereInterface
-
-

Implemented by

-
-
-
-
- -
-
-

Methods

-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
    - -
  • -

    Adds a where expression to the query.

    -

    Calling this method multiple times will combine the expressions using and.

    -

    Also see whereRef

    - - -

    Examples

    -
    -
    const person = await db
    .selectFrom('person')
    .selectAll()
    .where('first_name', '=', 'Jennifer')
    .where('age', '>', 40)
    .executeTakeFirst() -
    -

    The generated SQL (PostgreSQL):

    -
    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:

    -
    sql`your operator`
    -
    -

    You can add expressions conditionally like this:

    -
    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)
    }

    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 ExpressionBuilder passed to the callback:

    -
    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):

    -
    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:

    -
    const persons = await db
    .selectFrom('person')
    .selectAll()
    .where('person.id', 'in', [100, 200, 300])
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "person" where "id" in ($1, $2, $3)
    -
    -

    For complex where expressions you can pass in a single callback and -use the ExpressionBuilder to build your expression:

    -
    const persons = await db
    .selectFrom('person')
    .selectAll('person')
    .where(({ cmpr, or, and, not, exists, selectFrom, val }) => and([
    or([
    cmpr('first_name', '=', firstName),
    cmpr('age', '<', maxAge)
    ]),
    not(exists(
    selectFrom('pet').select('pet.id').whereRef('pet.owner_id', '=', 'person.id')
    ))
    ])) -
    -

    The generated SQL (PostgreSQL):

    -
    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 sql tag -as any of the arguments, including the operator:

    -
    importsql } from 'kysely'

    const persons = await db
    .selectFrom('person')
    .selectAll()
    .where(
    sql`coalesce(first_name, last_name)`,
    'like',
    '%' + name + '%',
    )
    .execute() -
    -

    The generated SQL (PostgreSQL):

    -
    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 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 sql tag or db.dynamic. The example below -uses both:

    -
    importsql } from 'kysely'
    const { ref } = db.dynamic

    const persons = await db
    .selectFrom('person')
    .selectAll()
    .where(ref(columnFromUserInput), '=', 1)
    .where(sql.id(columnFromUserInput), '=', 2)
    .execute() -
    -
    -
    -

    Type Parameters

    -
      -
    • -

      RE extends string | Expression<any> | DynamicReferenceBuilder<any> | SelectQueryBuilder<any, any, {}> | SelectQueryBuilderFactory<DB, TB, {}> | ExpressionFactory<DB, TB, any>

    -
    -

    Parameters

    -
    -

    Returns WhereInterface<DB, TB>

  • - -
  • -
    -

    Parameters

    -
    -

    Returns WhereInterface<DB, TB>

  • - -
  • -
    -

    Parameters

    -
    -

    Returns 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:

    -
    db.selectFrom(['person', 'pet'])
    .selectAll()
    .whereRef('person.first_name', '=', 'pet.name') -
    -

    The generated SQL (PostgreSQL):

    -
    select * from "person", "pet" where "person"."first_name" = "pet"."name"
    -
    -

    Usage in a subquery:

    -
    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"

    -
    -
    -

    Parameters

    -
    -

    Returns WhereInterface<DB, TB>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/WhereNode.html b/docs/interfaces/WhereNode.html deleted file mode 100644 index db053c168..000000000 --- a/docs/interfaces/WhereNode.html +++ /dev/null @@ -1,78 +0,0 @@ -WhereNode | kysely
-
- -
-
-
-
- -

Interface WhereNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
kind: "WhereNode"
-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/interfaces/WithNode.html b/docs/interfaces/WithNode.html deleted file mode 100644 index 1546331f2..000000000 --- a/docs/interfaces/WithNode.html +++ /dev/null @@ -1,85 +0,0 @@ -WithNode | kysely
-
- -
-
-
-
- -

Interface WithNode

-
-

Hierarchy

-
-
-
-
- -
-
-

Properties

-
-
-

Properties

-
- -
expressions: readonly CommonTableExpressionNode[]
-
- -
kind: "WithNode"
-
- -
recursive?: boolean
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/modules.html b/docs/modules.html deleted file mode 100644 index 4869dfd9b..000000000 --- a/docs/modules.html +++ /dev/null @@ -1,829 +0,0 @@ -kysely
-
- -
-
-
-
-

kysely

-
-
-

Index

-
-

Classes

-
-
-

Interfaces

-
AddColumnNode -AddConstraintNode -AggregateFunctionBuilderProps -AggregateFunctionNode -AliasNode -AliasedExpression -AlterColumnNode -AlterTableBuilderProps -AlterTableColumnAlteringBuilderProps -AlterTableNode -AndNode -BinaryOperationNode -CamelCasePluginOptions -CaseNode -CheckConstraintNode -ColumnAlteringInterface -ColumnDefinitionNode -ColumnMetadata -ColumnNode -ColumnUpdateNode -CommonTableExpressionNameNode -CommonTableExpressionNode -Compilable -CompiledQuery -ConnectionProvider -CreateIndexBuilderProps -CreateIndexNode -CreateSchemaBuilderProps -CreateSchemaNode -CreateTableBuilderProps -CreateTableNode -CreateTypeBuilderProps -CreateTypeNode -CreateViewBuilderProps -CreateViewNode -DataTypeNode -DatabaseConnection -DatabaseIntrospector -DatabaseMetadata -DatabaseMetadataOptions -DefaultInsertValueNode -DefaultValueNode -DeleteQueryBuilderProps -DeleteQueryNode -Dialect -DialectAdapter -Driver -DropColumnNode -DropConstraintNode -DropIndexBuilderProps -DropIndexNode -DropSchemaBuilderProps -DropSchemaNode -DropTableBuilderProps -DropTableNode -DropTypeBuilderProps -DropTypeNode -DropViewBuilderProps -DropViewNode -ErrorLogEvent -ExplainNode -Explainable -Expression -ExpressionBuilder -FileMigrationProviderFS -FileMigrationProviderPath -FileMigrationProviderProps -ForeignKeyConstraintBuilderInterface -ForeignKeyConstraintNode -FromNode -FunctionModule -GeneratedNode -GroupByItemNode -GroupByNode -HavingInterface -HavingNode -IdentifierNode -InsertQueryBuilderProps -InsertQueryNode -JoinBuilderProps -JoinNode -KyselyConfig -KyselyPlugin -KyselyProps -LimitNode -ListNode -Migration -MigrationInfo -MigrationLockOptions -MigrationProvider -MigrationResult -MigrationResultSet -MigratorProps -ModifyColumnNode -MysqlDialectConfig -MysqlOkPacket -MysqlPool -MysqlPoolConnection -MysqlStream -MysqlStreamOptions -NoMigrations -OffsetNode -OnConflictBuilderProps -OnConflictNode -OnDuplicateKeyNode -OnNode -OperationNode -OperationNodeSource -OperatorNode -OrNode -OrderByItemNode -OrderByNode -OverNode -ParensNode -PartitionByItemNode -PartitionByNode -PluginTransformQueryArgs -PluginTransformResultArgs -PostgresCursor -PostgresDialectConfig -PostgresPool -PostgresPoolClient -PostgresQueryResult -PostgresStream -PrimaryKeyConstraintNode -PrimitiveValueListNode -QueryCompiler -QueryCreatorProps -QueryExecutor -QueryLogEvent -QueryResult -RawBuilderProps -RawNode -ReferenceNode -ReferencesNode -RenameColumnNode -ReturningInterface -ReturningNode -SchemaMetadata -SelectAllNode -SelectQueryBuilderProps -SelectQueryNode -SelectionNode -SetOperationNode -Sql -SqliteDatabase -SqliteDialectConfig -SqliteStatement -Streamable -TableMetadata -TableNode -TransactionSettings -UnaryOperationNode -UniqueConstraintNode -UpdateQueryBuilderProps -UpdateQueryNode -UsingNode -ValueListNode -ValueNode -ValuesNode -WhenNode -WhereInterface -WhereNode -WithNode -
-
-

Type Aliases

-
AlterColumnBuilderCallback -AlterColumnNodeProps -AlterTableColumnAlterationNode -AlterTableNodeTableProps -AnyAliasedColumn -AnyAliasedColumnWithTable -AnyColumn -AnyColumnWithTable -AnySelectQueryBuilder -ArithmeticOperator -BinaryOperator -ColumnBuilderCallback -ColumnDataType -ColumnDefinitionBuilderCallback -ColumnDefinitionNodeProps -ColumnType -ComparisonOperator -ComparisonOperatorExpression -ConstraintNode -CreateIndexNodeProps -CreateSchemaNodeParams -CreateTableNodeParams -CreateTypeNodeParams -CreateViewNodeParams -DataTypeParams -DeleteQueryBuilderWithFullJoin -DeleteQueryBuilderWithInnerJoin -DeleteQueryBuilderWithLeftJoin -DeleteQueryBuilderWithRightJoin -DropConstraintNodeProps -DropIndexNodeProps -DropSchemaNodeParams -DropTablexNodeParams -DropTypeNodeParams -DropViewNodeParams -Equals -ExistsExpression -ExplainFormat -ExtractTypeFromReferenceExpression -ExtractTypeFromStringReference -ForeignKeyConstraintBuilderCallback -ForeignKeyConstraintNodeProps -Generated -GeneratedAlways -GeneratedNodeParams -HavingExpressionFactory -IndexType -InferResult -InsertObject -InsertQueryNodeProps -InsertType -Insertable -IsolationLevel -JoinCallbackExpression -JoinReferenceExpression -JoinType -LogConfig -LogEvent -LogLevel -Logger -MysqlQueryResult -NoResultErrorConstructor -NonNullableInsertKeys -NullableInsertKeys -OnCommitAction -OnConflictDatabase -OnConflictNodeProps -OnConflictTables -OnDuplicateKeyNodeProps -OnModifyForeignAction -OperandValueExpression -OperandValueExpressionOrList -OperationNodeKind -Operator -OrderByDirectionExpression -OrderByExpression -OverBuilderCallback -PostgresCursorConstructor -QueryNode -ReferenceExpression -ReferenceExpressionOrList -RootOperationNode -SelectArg -SelectExpression -SelectQueryBuilderWithFullJoin -SelectQueryBuilderWithInnerJoin -SelectQueryBuilderWithLeftJoin -SelectQueryBuilderWithRightJoin -SelectType -Selectable -Selection -SetOperator -SimpleReferenceExpression -Simplify -SqlBool -StringReference -TableExpression -TableExpressionOrList -UnaryFilterOperator -UnaryOperator -UnknownRow -UpdateKeys -UpdateObject -UpdateQueryBuilderWithFullJoin -UpdateQueryBuilderWithInnerJoin -UpdateQueryBuilderWithLeftJoin -UpdateQueryBuilderWithRightJoin -UpdateType -UpdateValuesNode -Updateable -ValueExpression -ValueExpressionOrList -ValuesItemNode -WhereExpressionFactory -WithNodeParams -
-
-

Variables

-
-
-

Functions

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/AlterColumnBuilderCallback.html b/docs/types/AlterColumnBuilderCallback.html deleted file mode 100644 index b0de03a99..000000000 --- a/docs/types/AlterColumnBuilderCallback.html +++ /dev/null @@ -1,444 +0,0 @@ -AlterColumnBuilderCallback | kysely
-
- -
-
-
-
- -

Type alias AlterColumnBuilderCallback

-
AlterColumnBuilderCallback: ((builder: AlterColumnBuilder) => AlteredColumnBuilder)
-
-

Type declaration

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/AlterColumnNodeProps.html b/docs/types/AlterColumnNodeProps.html deleted file mode 100644 index b14ab15e5..000000000 --- a/docs/types/AlterColumnNodeProps.html +++ /dev/null @@ -1,431 +0,0 @@ -AlterColumnNodeProps | kysely
-
- -
-
-
-
- -

Type alias AlterColumnNodeProps

-
AlterColumnNodeProps: Omit<AlterColumnNode, "kind" | "column">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/AlterTableColumnAlterationNode.html b/docs/types/AlterTableColumnAlterationNode.html deleted file mode 100644 index 4ae753c70..000000000 --- a/docs/types/AlterTableColumnAlterationNode.html +++ /dev/null @@ -1,431 +0,0 @@ -AlterTableColumnAlterationNode | kysely
-
- -
-
-
-
- -

Type alias AlterTableColumnAlterationNode

-
AlterTableColumnAlterationNode: RenameColumnNode | AddColumnNode | DropColumnNode | AlterColumnNode | ModifyColumnNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/AlterTableNodeTableProps.html b/docs/types/AlterTableNodeTableProps.html deleted file mode 100644 index 0653828e9..000000000 --- a/docs/types/AlterTableNodeTableProps.html +++ /dev/null @@ -1,431 +0,0 @@ -AlterTableNodeTableProps | kysely
-
- -
-
-
-
- -

Type alias AlterTableNodeTableProps

-
AlterTableNodeTableProps: Pick<AlterTableNode, "renameTo" | "setSchema" | "addConstraint" | "dropConstraint">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/AnyAliasedColumn.html b/docs/types/AnyAliasedColumn.html deleted file mode 100644 index 63fbf95c6..000000000 --- a/docs/types/AnyAliasedColumn.html +++ /dev/null @@ -1,440 +0,0 @@ -AnyAliasedColumn | kysely
-
- -
-
-
-
- -

Type alias AnyAliasedColumn<DB, TB>

-
AnyAliasedColumn<DB, TB>: { [ T in TB]: T extends string ? keyof DB[T] extends string ? `${keyof DB[T]} as ${string}` : never : never }[TB]
-

Just like AnyColumn but with a as <string> suffix.

-
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/AnyAliasedColumnWithTable.html b/docs/types/AnyAliasedColumnWithTable.html deleted file mode 100644 index 692f7631f..000000000 --- a/docs/types/AnyAliasedColumnWithTable.html +++ /dev/null @@ -1,440 +0,0 @@ -AnyAliasedColumnWithTable | kysely
-
- -
-
-
-
- -

Type alias AnyAliasedColumnWithTable<DB, TB>

-
AnyAliasedColumnWithTable<DB, TB>: { [ T in TB]: T extends string ? keyof DB[T] extends string ? `${T}.${keyof DB[T]} as ${string}` : never : never }[TB]
-

Just like AnyColumnWithTable but with a as <string> suffix.

-
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/AnyColumn.html b/docs/types/AnyColumn.html deleted file mode 100644 index 9f0b51892..000000000 --- a/docs/types/AnyColumn.html +++ /dev/null @@ -1,444 +0,0 @@ -AnyColumn | kysely
-
- -
-
-
-
- -

Type alias AnyColumn<DB, TB>

-
AnyColumn<DB, TB>: DrainOuterGeneric<{ [ T in TB]: keyof DB[T] }[TB] & string>
-

Given a database type and a union of table names in that db, returns -a union type with all possible column names.

-

Example:

-
interface Person {
id: number
}

interface Pet {
name: string
species: 'cat' | 'dog'
}

interface Movie {
stars: number
}

interface Database {
person: Person
pet: Pet
movie: Movie
}

type Columns = AnyColumn<Database, 'person' | 'pet'>

// Columns == 'id' | 'name' | 'species' -
-
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/AnyColumnWithTable.html b/docs/types/AnyColumnWithTable.html deleted file mode 100644 index 6dd6f79ec..000000000 --- a/docs/types/AnyColumnWithTable.html +++ /dev/null @@ -1,444 +0,0 @@ -AnyColumnWithTable | kysely
-
- -
-
-
-
- -

Type alias AnyColumnWithTable<DB, TB>

-
AnyColumnWithTable<DB, TB>: { [ T in TB]: T extends string ? keyof DB[T] extends string ? `${T}.${keyof DB[T]}` : never : never }[TB]
-

Given a database type and a union of table names in that db, returns -a union type with all possible table.column combinations.

-

Example:

-
interface Person {
id: number
}

interface Pet {
name: string
species: 'cat' | 'dog'
}

interface Movie {
stars: number
}

interface Database {
person: Person
pet: Pet
movie: Movie
}

type Columns = AnyColumnWithTable<Database, 'person' | 'pet'>

// Columns == 'person.id' | 'pet.name' | 'pet.species' -
-
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/AnySelectQueryBuilder.html b/docs/types/AnySelectQueryBuilder.html deleted file mode 100644 index bfaa3a81c..000000000 --- a/docs/types/AnySelectQueryBuilder.html +++ /dev/null @@ -1,433 +0,0 @@ -AnySelectQueryBuilder | kysely
-
- -
-
-
-
- -

Type alias AnySelectQueryBuilder

-
AnySelectQueryBuilder: SelectQueryBuilder<any, any, any>
-

Any select query builder.

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ArithmeticOperator.html b/docs/types/ArithmeticOperator.html deleted file mode 100644 index 3ec54544f..000000000 --- a/docs/types/ArithmeticOperator.html +++ /dev/null @@ -1,431 +0,0 @@ -ArithmeticOperator | kysely
-
- -
-
-
-
- -

Type alias ArithmeticOperator

-
ArithmeticOperator: typeof ARITHMETIC_OPERATORS[number]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/BinaryOperator.html b/docs/types/BinaryOperator.html deleted file mode 100644 index 22608842a..000000000 --- a/docs/types/BinaryOperator.html +++ /dev/null @@ -1,431 +0,0 @@ -BinaryOperator | kysely
-
- -
-
-
-
- -

Type alias BinaryOperator

-
BinaryOperator: typeof BINARY_OPERATORS[number]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ColumnBuilderCallback.html b/docs/types/ColumnBuilderCallback.html deleted file mode 100644 index a83fabb38..000000000 --- a/docs/types/ColumnBuilderCallback.html +++ /dev/null @@ -1,444 +0,0 @@ -ColumnBuilderCallback | kysely
-
- -
-
-
-
- -

Type alias ColumnBuilderCallback

-
ColumnBuilderCallback: ((builder: ColumnDefinitionBuilder) => ColumnDefinitionBuilder)
-
-

Type declaration

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ColumnDataType.html b/docs/types/ColumnDataType.html deleted file mode 100644 index 24ac45849..000000000 --- a/docs/types/ColumnDataType.html +++ /dev/null @@ -1,431 +0,0 @@ -ColumnDataType | kysely
-
- -
-
-
-
- -

Type alias ColumnDataType

-
ColumnDataType: "varchar" | `varchar(${number})` | "char" | `char(${number})` | "text" | "integer" | "int2" | "int4" | "int8" | "bigint" | "boolean" | "real" | "double precision" | "float4" | "float8" | "decimal" | `decimal(${number}, ${number})` | "numeric" | `numeric(${number}, ${number})` | "binary" | `binary(${number})` | "bytea" | "date" | "datetime" | `datetime(${number})` | "time" | `time(${number})` | "timetz" | `timetz(${number})` | "timestamp" | `timestamp(${number})` | "timestamptz" | `timestamptz(${number})` | "serial" | "bigserial" | "uuid" | "json" | "jsonb" | "blob"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ColumnDefinitionBuilderCallback.html b/docs/types/ColumnDefinitionBuilderCallback.html deleted file mode 100644 index 1fee3b4fc..000000000 --- a/docs/types/ColumnDefinitionBuilderCallback.html +++ /dev/null @@ -1,444 +0,0 @@ -ColumnDefinitionBuilderCallback | kysely
-
- -
-
-
-
- -

Type alias ColumnDefinitionBuilderCallback

-
ColumnDefinitionBuilderCallback: ((builder: ColumnDefinitionBuilder) => ColumnDefinitionBuilder)
-
-

Type declaration

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ColumnDefinitionNodeProps.html b/docs/types/ColumnDefinitionNodeProps.html deleted file mode 100644 index 4cd68cafe..000000000 --- a/docs/types/ColumnDefinitionNodeProps.html +++ /dev/null @@ -1,431 +0,0 @@ -ColumnDefinitionNodeProps | kysely
-
- -
-
-
-
- -

Type alias ColumnDefinitionNodeProps

-
ColumnDefinitionNodeProps: Omit<Partial<ColumnDefinitionNode>, "kind" | "dataType">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ColumnType.html b/docs/types/ColumnType.html deleted file mode 100644 index b8a2c32d9..000000000 --- a/docs/types/ColumnType.html +++ /dev/null @@ -1,475 +0,0 @@ -ColumnType | kysely
-
- -
-
-
-
- -

Type alias ColumnType<SelectType, InsertType, UpdateType>

-
ColumnType<SelectType, InsertType, UpdateType>: {
    __insert__: InsertType;
    __select__: SelectType;
    __update__: UpdateType;
}
-

This type can be used to specify a different type for -select, insert and update operations.

-

Also see the Generated type.

- - -

Examples

-
-

The next example defines a number column that is optional -in inserts and updates. All columns are always optional -in updates so therefore we don't need to specify undefined -for the update type. The type below is useful for all kinds of -database generated columns like identifiers. The Generated -type is actually just a shortcut for the type in this example:

-
ColumnType<number, number | undefined, number>
-
-

The above example makes the column optional in inserts -and updates, but you can still choose to provide the -column. If you want to prevent insertion/update you -can se the type as never:

-
ColumnType<number, never, never>
-
-

Here's one more example where the type is different -for each different operation:

-
ColumnType<Date, string, never>
-
-
-
-

Type Parameters

-
    -
  • -

    SelectType

  • -
  • -

    InsertType = SelectType

  • -
  • -

    UpdateType = SelectType

-
-

Type declaration

-
    -
  • -
    Readonly __insert__: InsertType
  • -
  • -
    Readonly __select__: SelectType
  • -
  • -
    Readonly __update__: UpdateType
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ComparisonOperator.html b/docs/types/ComparisonOperator.html deleted file mode 100644 index 84493e582..000000000 --- a/docs/types/ComparisonOperator.html +++ /dev/null @@ -1,431 +0,0 @@ -ComparisonOperator | kysely
-
- -
-
-
-
- -

Type alias ComparisonOperator

-
ComparisonOperator: typeof COMPARISON_OPERATORS[number]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ComparisonOperatorExpression.html b/docs/types/ComparisonOperatorExpression.html deleted file mode 100644 index ca3bc00a7..000000000 --- a/docs/types/ComparisonOperatorExpression.html +++ /dev/null @@ -1,431 +0,0 @@ -ComparisonOperatorExpression | kysely
-
- -
-
-
-
- -

Type alias ComparisonOperatorExpression

-
ComparisonOperatorExpression: ComparisonOperator | Expression<unknown>
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ConstraintNode.html b/docs/types/ConstraintNode.html deleted file mode 100644 index 798a9f15e..000000000 --- a/docs/types/ConstraintNode.html +++ /dev/null @@ -1,431 +0,0 @@ -ConstraintNode | kysely
-
- -
-
-
-
- -

Type alias ConstraintNode

-
ConstraintNode: PrimaryKeyConstraintNode | UniqueConstraintNode | CheckConstraintNode | ForeignKeyConstraintNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/CreateIndexNodeProps.html b/docs/types/CreateIndexNodeProps.html deleted file mode 100644 index 30ac627e7..000000000 --- a/docs/types/CreateIndexNodeProps.html +++ /dev/null @@ -1,431 +0,0 @@ -CreateIndexNodeProps | kysely
-
- -
-
-
-
- -

Type alias CreateIndexNodeProps

-
CreateIndexNodeProps: Omit<CreateIndexNode, "kind" | "name">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/CreateSchemaNodeParams.html b/docs/types/CreateSchemaNodeParams.html deleted file mode 100644 index 219eb967b..000000000 --- a/docs/types/CreateSchemaNodeParams.html +++ /dev/null @@ -1,431 +0,0 @@ -CreateSchemaNodeParams | kysely
-
- -
-
-
-
- -

Type alias CreateSchemaNodeParams

-
CreateSchemaNodeParams: Omit<Partial<CreateSchemaNode>, "kind" | "schema">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/CreateTableNodeParams.html b/docs/types/CreateTableNodeParams.html deleted file mode 100644 index ce185be6c..000000000 --- a/docs/types/CreateTableNodeParams.html +++ /dev/null @@ -1,431 +0,0 @@ -CreateTableNodeParams | kysely
-
- -
-
-
-
- -

Type alias CreateTableNodeParams

-
CreateTableNodeParams: Omit<CreateTableNode, "kind" | "table" | "columns" | "constraints" | "frontModifiers" | "endModifiers">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/CreateTypeNodeParams.html b/docs/types/CreateTypeNodeParams.html deleted file mode 100644 index d16e97e78..000000000 --- a/docs/types/CreateTypeNodeParams.html +++ /dev/null @@ -1,431 +0,0 @@ -CreateTypeNodeParams | kysely
-
- -
-
-
-
- -

Type alias CreateTypeNodeParams

-
CreateTypeNodeParams: Omit<Partial<CreateTypeNode>, "kind">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/CreateViewNodeParams.html b/docs/types/CreateViewNodeParams.html deleted file mode 100644 index 052ce0bde..000000000 --- a/docs/types/CreateViewNodeParams.html +++ /dev/null @@ -1,431 +0,0 @@ -CreateViewNodeParams | kysely
-
- -
-
-
-
- -

Type alias CreateViewNodeParams

-
CreateViewNodeParams: Omit<Partial<CreateViewNode>, "kind" | "name">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/DataTypeParams.html b/docs/types/DataTypeParams.html deleted file mode 100644 index c7b886365..000000000 --- a/docs/types/DataTypeParams.html +++ /dev/null @@ -1,431 +0,0 @@ -DataTypeParams | kysely
-
- -
-
-
-
- -

Type alias DataTypeParams

-
DataTypeParams: Omit<DataTypeNode, "kind" | "dataType">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/DeleteQueryBuilderWithFullJoin.html b/docs/types/DeleteQueryBuilderWithFullJoin.html deleted file mode 100644 index 50a85b6d5..000000000 --- a/docs/types/DeleteQueryBuilderWithFullJoin.html +++ /dev/null @@ -1,442 +0,0 @@ -DeleteQueryBuilderWithFullJoin | kysely
-
- -
-
-
-
- -

Type alias DeleteQueryBuilderWithFullJoin<DB, TB, O, TE>

-
DeleteQueryBuilderWithFullJoin<DB, TB, O, TE>: TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? OuterJoinedBuilder<DB, TB, O, A, DB[T]> : never : TE extends keyof DB ? OuterJoinedBuilder<DB, TB, O, TE, DB[TE]> : TE extends AliasedExpression<infer QO, infer QA> ? OuterJoinedBuilder<DB, TB, O, QA, QO> : TE extends ((qb: any) => AliasedExpression<infer QO, infer QA>) ? OuterJoinedBuilder<DB, TB, O, QA, QO> : never
-
-

Type Parameters

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/DeleteQueryBuilderWithInnerJoin.html b/docs/types/DeleteQueryBuilderWithInnerJoin.html deleted file mode 100644 index bba7416e3..000000000 --- a/docs/types/DeleteQueryBuilderWithInnerJoin.html +++ /dev/null @@ -1,442 +0,0 @@ -DeleteQueryBuilderWithInnerJoin | kysely
-
- -
-
-
-
- -

Type alias DeleteQueryBuilderWithInnerJoin<DB, TB, O, TE>

-
DeleteQueryBuilderWithInnerJoin<DB, TB, O, TE>: TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? InnerJoinedBuilder<DB, TB, O, A, DB[T]> : never : TE extends keyof DB ? DeleteQueryBuilder<DB, TB | TE, O> : TE extends AliasedExpression<infer QO, infer QA> ? InnerJoinedBuilder<DB, TB, O, QA, QO> : TE extends ((qb: any) => AliasedExpression<infer QO, infer QA>) ? InnerJoinedBuilder<DB, TB, O, QA, QO> : never
-
-

Type Parameters

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/DeleteQueryBuilderWithLeftJoin.html b/docs/types/DeleteQueryBuilderWithLeftJoin.html deleted file mode 100644 index bbf76b2b8..000000000 --- a/docs/types/DeleteQueryBuilderWithLeftJoin.html +++ /dev/null @@ -1,442 +0,0 @@ -DeleteQueryBuilderWithLeftJoin | kysely
-
- -
-
-
-
- -

Type alias DeleteQueryBuilderWithLeftJoin<DB, TB, O, TE>

-
DeleteQueryBuilderWithLeftJoin<DB, TB, O, TE>: TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? LeftJoinedBuilder<DB, TB, O, A, DB[T]> : never : TE extends keyof DB ? LeftJoinedBuilder<DB, TB, O, TE, DB[TE]> : TE extends AliasedExpression<infer QO, infer QA> ? LeftJoinedBuilder<DB, TB, O, QA, QO> : TE extends ((qb: any) => AliasedExpression<infer QO, infer QA>) ? LeftJoinedBuilder<DB, TB, O, QA, QO> : never
-
-

Type Parameters

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/DeleteQueryBuilderWithRightJoin.html b/docs/types/DeleteQueryBuilderWithRightJoin.html deleted file mode 100644 index ce7fb696a..000000000 --- a/docs/types/DeleteQueryBuilderWithRightJoin.html +++ /dev/null @@ -1,442 +0,0 @@ -DeleteQueryBuilderWithRightJoin | kysely
-
- -
-
-
-
- -

Type alias DeleteQueryBuilderWithRightJoin<DB, TB, O, TE>

-
DeleteQueryBuilderWithRightJoin<DB, TB, O, TE>: TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? RightJoinedBuilder<DB, TB, O, A, DB[T]> : never : TE extends keyof DB ? RightJoinedBuilder<DB, TB, O, TE, DB[TE]> : TE extends AliasedExpression<infer QO, infer QA> ? RightJoinedBuilder<DB, TB, O, QA, QO> : TE extends ((qb: any) => AliasedExpression<infer QO, infer QA>) ? RightJoinedBuilder<DB, TB, O, QA, QO> : never
-
-

Type Parameters

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/DropConstraintNodeProps.html b/docs/types/DropConstraintNodeProps.html deleted file mode 100644 index 88e3c01f4..000000000 --- a/docs/types/DropConstraintNodeProps.html +++ /dev/null @@ -1,431 +0,0 @@ -DropConstraintNodeProps | kysely
-
- -
-
-
-
- -

Type alias DropConstraintNodeProps

-
DropConstraintNodeProps: Omit<DropConstraintNode, "kind" | "constraintName">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/DropIndexNodeProps.html b/docs/types/DropIndexNodeProps.html deleted file mode 100644 index 9c16b3a84..000000000 --- a/docs/types/DropIndexNodeProps.html +++ /dev/null @@ -1,431 +0,0 @@ -DropIndexNodeProps | kysely
-
- -
-
-
-
- -

Type alias DropIndexNodeProps

-
DropIndexNodeProps: Omit<DropIndexNode, "kind" | "name">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/DropSchemaNodeParams.html b/docs/types/DropSchemaNodeParams.html deleted file mode 100644 index 0144f6fb2..000000000 --- a/docs/types/DropSchemaNodeParams.html +++ /dev/null @@ -1,431 +0,0 @@ -DropSchemaNodeParams | kysely
-
- -
-
-
-
- -

Type alias DropSchemaNodeParams

-
DropSchemaNodeParams: Omit<Partial<DropSchemaNode>, "kind" | "schema">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/DropTablexNodeParams.html b/docs/types/DropTablexNodeParams.html deleted file mode 100644 index 0fb7eab0d..000000000 --- a/docs/types/DropTablexNodeParams.html +++ /dev/null @@ -1,431 +0,0 @@ -DropTablexNodeParams | kysely
-
- -
-
-
-
- -

Type alias DropTablexNodeParams

-
DropTablexNodeParams: Omit<Partial<DropTableNode>, "kind" | "table">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/DropTypeNodeParams.html b/docs/types/DropTypeNodeParams.html deleted file mode 100644 index 62292bd6e..000000000 --- a/docs/types/DropTypeNodeParams.html +++ /dev/null @@ -1,431 +0,0 @@ -DropTypeNodeParams | kysely
-
- -
-
-
-
- -

Type alias DropTypeNodeParams

-
DropTypeNodeParams: Omit<Partial<DropTypeNode>, "kind" | "name">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/DropViewNodeParams.html b/docs/types/DropViewNodeParams.html deleted file mode 100644 index a9ebce94e..000000000 --- a/docs/types/DropViewNodeParams.html +++ /dev/null @@ -1,431 +0,0 @@ -DropViewNodeParams | kysely
-
- -
-
-
-
- -

Type alias DropViewNodeParams

-
DropViewNodeParams: Omit<Partial<DropViewNode>, "kind" | "name">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/Equals.html b/docs/types/Equals.html deleted file mode 100644 index ae7ac12f9..000000000 --- a/docs/types/Equals.html +++ /dev/null @@ -1,440 +0,0 @@ -Equals | kysely
-
- -
-
-
-
- -

Type alias Equals<T, U>

-
Equals<T, U>: (<G>() => G extends T ? 1 : 2) extends (<G>() => G extends U ? 1 : 2) ? true : false
-

Evaluates to true if the types T and U are equal.

-
-
-

Type Parameters

-
    -
  • -

    T

  • -
  • -

    U

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ExistsExpression.html b/docs/types/ExistsExpression.html deleted file mode 100644 index 72743cf2e..000000000 --- a/docs/types/ExistsExpression.html +++ /dev/null @@ -1,438 +0,0 @@ -ExistsExpression | kysely
-
- -
-
-
-
- -

Type alias ExistsExpression<DB, TB>

-
ExistsExpression<DB, TB>: ExpressionOrFactory<DB, TB, any>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ExplainFormat.html b/docs/types/ExplainFormat.html deleted file mode 100644 index 2166f33fb..000000000 --- a/docs/types/ExplainFormat.html +++ /dev/null @@ -1,431 +0,0 @@ -ExplainFormat | kysely
-
- -
-
-
-
- -

Type alias ExplainFormat

-
ExplainFormat: "text" | "xml" | "json" | "yaml" | "traditional" | "tree"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ExtractTypeFromReferenceExpression.html b/docs/types/ExtractTypeFromReferenceExpression.html deleted file mode 100644 index 90ac2951f..000000000 --- a/docs/types/ExtractTypeFromReferenceExpression.html +++ /dev/null @@ -1,442 +0,0 @@ -ExtractTypeFromReferenceExpression | kysely
-
- -
-
-
-
- -

Type alias ExtractTypeFromReferenceExpression<DB, TB, RE, DV>

-
ExtractTypeFromReferenceExpression<DB, TB, RE, DV>: RE extends string ? SelectType<ExtractTypeFromStringReference<DB, TB, RE>> : RE extends SelectQueryBuilder<any, any, infer O> ? O[keyof O] | null : RE extends ((qb: any) => SelectQueryBuilder<any, any, infer O>) ? O[keyof O] | null : RE extends Expression<infer O> ? O : RE extends ((qb: any) => Expression<infer O>) ? O : DV
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    RE

  • -
  • -

    DV = unknown

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ExtractTypeFromStringReference.html b/docs/types/ExtractTypeFromStringReference.html deleted file mode 100644 index 606e5c247..000000000 --- a/docs/types/ExtractTypeFromStringReference.html +++ /dev/null @@ -1,442 +0,0 @@ -ExtractTypeFromStringReference | kysely
-
- -
-
-
-
- -

Type alias ExtractTypeFromStringReference<DB, TB, RE, DV>

-
ExtractTypeFromStringReference<DB, TB, RE, DV>: RE extends `${infer SC}.${infer T}.${infer C}` ? `${SC}.${T}` extends TB ? C extends keyof DB[`${SC}.${T}`] ? DB[`${SC}.${T}`][C] : never : never : RE extends `${infer T}.${infer C}` ? T extends TB ? C extends keyof DB[T] ? DB[T][C] : never : never : RE extends AnyColumn<DB, TB> ? ExtractColumnType<DB, TB, RE> : DV
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    RE extends string

  • -
  • -

    DV = unknown

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ForeignKeyConstraintBuilderCallback.html b/docs/types/ForeignKeyConstraintBuilderCallback.html deleted file mode 100644 index 14d866da4..000000000 --- a/docs/types/ForeignKeyConstraintBuilderCallback.html +++ /dev/null @@ -1,444 +0,0 @@ -ForeignKeyConstraintBuilderCallback | kysely
-
- -
-
-
-
- -

Type alias ForeignKeyConstraintBuilderCallback

-
ForeignKeyConstraintBuilderCallback: ((builder: ForeignKeyConstraintBuilder) => ForeignKeyConstraintBuilder)
-
-

Type declaration

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ForeignKeyConstraintNodeProps.html b/docs/types/ForeignKeyConstraintNodeProps.html deleted file mode 100644 index 4d226de2d..000000000 --- a/docs/types/ForeignKeyConstraintNodeProps.html +++ /dev/null @@ -1,431 +0,0 @@ -ForeignKeyConstraintNodeProps | kysely
-
- -
-
-
-
- -

Type alias ForeignKeyConstraintNodeProps

-
ForeignKeyConstraintNodeProps: Omit<ForeignKeyConstraintNode, "kind" | "columns" | "references">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/Generated.html b/docs/types/Generated.html deleted file mode 100644 index 40775abe4..000000000 --- a/docs/types/Generated.html +++ /dev/null @@ -1,443 +0,0 @@ -Generated | kysely
-
- -
-
-
-
- -

Type alias Generated<S>

-
Generated<S>: ColumnType<S, S | undefined, S>
-

A shortcut for defining database-generated columns. The type -is the same for all selects, inserts and updates but the -column is optional for inserts and updates.

-

The implementation:

-
// The update type is `S` instead of `S | undefined` because
// updates are always optional --> no need to specify optionality.
type Generated<S> = ColumnType<S, S | undefined, S> -
-
-
-

Type Parameters

-
    -
  • -

    S

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/GeneratedAlways.html b/docs/types/GeneratedAlways.html deleted file mode 100644 index d463bfeed..000000000 --- a/docs/types/GeneratedAlways.html +++ /dev/null @@ -1,440 +0,0 @@ -GeneratedAlways | kysely
-
- -
-
-
-
- -

Type alias GeneratedAlways<S>

-
GeneratedAlways<S>: ColumnType<S, never, never>
-

A shortcut for defining columns that are only database-generated -(like postgres GENERATED ALWAYS AS IDENTITY). No insert/update -is allowed.

-
-
-

Type Parameters

-
    -
  • -

    S

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/GeneratedNodeParams.html b/docs/types/GeneratedNodeParams.html deleted file mode 100644 index b2094f8dc..000000000 --- a/docs/types/GeneratedNodeParams.html +++ /dev/null @@ -1,431 +0,0 @@ -GeneratedNodeParams | kysely
-
- -
-
-
-
- -

Type alias GeneratedNodeParams

-
GeneratedNodeParams: Omit<GeneratedNode, "kind" | "expression">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/HavingExpressionFactory.html b/docs/types/HavingExpressionFactory.html deleted file mode 100644 index b905db967..000000000 --- a/docs/types/HavingExpressionFactory.html +++ /dev/null @@ -1,451 +0,0 @@ -HavingExpressionFactory | kysely
-
- -
-
-
-
- -

Type alias HavingExpressionFactory<DB, TB>

-
HavingExpressionFactory<DB, TB>: ((eb: HavingExpressionBuilder<DB, TB>) => Expression<SqlBool> | HavingExpressionBuilder<DB, TB>)
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-

Type declaration

-
    -
  • -
      -
    • (eb: HavingExpressionBuilder<DB, TB>): Expression<SqlBool> | HavingExpressionBuilder<DB, TB>
    • -
    • -
      -

      Parameters

      -
        -
      • -
        eb: HavingExpressionBuilder<DB, TB>
      -

      Returns Expression<SqlBool> | HavingExpressionBuilder<DB, TB>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/IndexType.html b/docs/types/IndexType.html deleted file mode 100644 index 29953f945..000000000 --- a/docs/types/IndexType.html +++ /dev/null @@ -1,431 +0,0 @@ -IndexType | kysely
-
- -
-
-
-
- -

Type alias IndexType

-
IndexType: "btree" | "hash" | "gist" | "gin"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/InferResult.html b/docs/types/InferResult.html deleted file mode 100644 index 6cdad5432..000000000 --- a/docs/types/InferResult.html +++ /dev/null @@ -1,449 +0,0 @@ -InferResult | kysely
-
- -
-
-
-
- -

Type alias InferResult<C>

-
InferResult<C>: C extends Compilable<infer O> ? ResolveResult<O> : C extends CompiledQuery<infer O> ? ResolveResult<O> : never
-

A helper type that allows inferring a select/insert/update/delete query's result -type from a query builder or compiled query.

- - -

Examples

-
-

Infer a query builder's result type:

-
import { InferResult } from 'kysely'

const query = db
.selectFrom('person')
.innerJoin('pet', 'pet.owner_id', 'person.id')
.select(['person.first_name', 'pet.name'])

type QueryResult = InferResult<typeof query> // { first_name: string; name: string; }[] -
-

Infer a compiled query's result type:

-
import { InferResult } from 'kysely'

const compiledQuery = db
.insertInto('person')
.values({
first_name: 'Foo',
last_name: 'Barson',
gender: 'other',
age: 15,
})
.returningAll()
.compile()

type QueryResult = InferResult<typeof compiledQuery> // Selectable<Person>[] -
-
-
-

Type Parameters

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/InsertObject.html b/docs/types/InsertObject.html deleted file mode 100644 index cd826570b..000000000 --- a/docs/types/InsertObject.html +++ /dev/null @@ -1,438 +0,0 @@ -InsertObject | kysely
-
- -
-
-
-
- -

Type alias InsertObject<DB, TB>

-
InsertObject<DB, TB>: { [ C in NonNullableInsertKeys<DB[TB]>]: ValueExpression<DB, TB, InsertType<DB[TB][C]>> } & { [ C in NullableInsertKeys<DB[TB]>]?: ValueExpression<DB, TB, InsertType<DB[TB][C]>> }
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/InsertQueryNodeProps.html b/docs/types/InsertQueryNodeProps.html deleted file mode 100644 index 783275d8a..000000000 --- a/docs/types/InsertQueryNodeProps.html +++ /dev/null @@ -1,431 +0,0 @@ -InsertQueryNodeProps | kysely
-
- -
-
-
-
- -

Type alias InsertQueryNodeProps

-
InsertQueryNodeProps: Omit<InsertQueryNode, "kind" | "into">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/InsertType.html b/docs/types/InsertType.html deleted file mode 100644 index 474f9d1bd..000000000 --- a/docs/types/InsertType.html +++ /dev/null @@ -1,436 +0,0 @@ -InsertType | kysely
-
- -
-
-
-
- -

Type alias InsertType<T>

-
InsertType<T>: T extends ColumnType<any, infer I, any> ? I : T
-
-

Type Parameters

-
    -
  • -

    T

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/Insertable.html b/docs/types/Insertable.html deleted file mode 100644 index 267f94ccf..000000000 --- a/docs/types/Insertable.html +++ /dev/null @@ -1,445 +0,0 @@ -Insertable | kysely
-
- -
-
-
-
- -

Type alias Insertable<R>

-
Insertable<R>: { [ K in NonNullableInsertKeys<R>]: InsertType<R[K]> } & { [ K in NullableInsertKeys<R>]?: InsertType<R[K]> }
-

Given a table interface, extracts the insert type from all -ColumnType types.

- - -

Examples

-
-
interface PersonTable {
id: Generated<number>
first_name: string
modified_at: ColumnType<Date, string, never>
}

type InsertablePerson = Insertable<PersonTable>
// {
// id?: number,
// first_name: string
// modified_at: string
// } -
-
-
-

Type Parameters

-
    -
  • -

    R

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/IsolationLevel.html b/docs/types/IsolationLevel.html deleted file mode 100644 index 40cce13c0..000000000 --- a/docs/types/IsolationLevel.html +++ /dev/null @@ -1,431 +0,0 @@ -IsolationLevel | kysely
-
- -
-
-
-
- -

Type alias IsolationLevel

-
IsolationLevel: ArrayItemType<typeof TRANSACTION_ISOLATION_LEVELS>
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/JoinCallbackExpression.html b/docs/types/JoinCallbackExpression.html deleted file mode 100644 index 08a3f42e7..000000000 --- a/docs/types/JoinCallbackExpression.html +++ /dev/null @@ -1,453 +0,0 @@ -JoinCallbackExpression | kysely
-
- -
-
-
-
- -

Type alias JoinCallbackExpression<DB, TB, TE>

-
JoinCallbackExpression<DB, TB, TE>: ((join: JoinBuilder<From<DB, TE>, FromTables<DB, TB, TE>>) => JoinBuilder<any, any>)
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    TE

-
-

Type declaration

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/JoinReferenceExpression.html b/docs/types/JoinReferenceExpression.html deleted file mode 100644 index ddae5db9c..000000000 --- a/docs/types/JoinReferenceExpression.html +++ /dev/null @@ -1,440 +0,0 @@ -JoinReferenceExpression | kysely
-
- -
-
-
-
- -

Type alias JoinReferenceExpression<DB, TB, TE>

-
JoinReferenceExpression<DB, TB, TE>: AnyJoinColumn<DB, TB, TE> | AnyJoinColumnWithTable<DB, TB, TE>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    TE

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/JoinType.html b/docs/types/JoinType.html deleted file mode 100644 index e24cc8911..000000000 --- a/docs/types/JoinType.html +++ /dev/null @@ -1,431 +0,0 @@ -JoinType | kysely
-
- -
-
-
-
- -

Type alias JoinType

-
JoinType: "InnerJoin" | "LeftJoin" | "RightJoin" | "FullJoin" | "LateralInnerJoin" | "LateralLeftJoin"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/LogConfig.html b/docs/types/LogConfig.html deleted file mode 100644 index b777893a5..000000000 --- a/docs/types/LogConfig.html +++ /dev/null @@ -1,431 +0,0 @@ -LogConfig | kysely
-
- -
-
-
-
- -

Type alias LogConfig

-
LogConfig: ReadonlyArray<LogLevel> | Logger
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/LogEvent.html b/docs/types/LogEvent.html deleted file mode 100644 index 39d5af10f..000000000 --- a/docs/types/LogEvent.html +++ /dev/null @@ -1,431 +0,0 @@ -LogEvent | kysely
-
- -
-
-
-
- -

Type alias LogEvent

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/LogLevel.html b/docs/types/LogLevel.html deleted file mode 100644 index 3c1056bbc..000000000 --- a/docs/types/LogLevel.html +++ /dev/null @@ -1,431 +0,0 @@ -LogLevel | kysely
-
- -
-
-
-
- -

Type alias LogLevel

-
LogLevel: ArrayItemType<typeof LOG_LEVELS>
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/Logger.html b/docs/types/Logger.html deleted file mode 100644 index 9810381bd..000000000 --- a/docs/types/Logger.html +++ /dev/null @@ -1,444 +0,0 @@ -Logger | kysely
-
- -
-
-
-
- -

Type alias Logger

-
Logger: ((event: LogEvent) => void | Promise<void>)
-
-

Type declaration

-
    -
  • -
      -
    • (event: LogEvent): void | Promise<void>
    • -
    • -
      -

      Parameters

      -
      -

      Returns void | Promise<void>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/MysqlQueryResult.html b/docs/types/MysqlQueryResult.html deleted file mode 100644 index af6bb3fd0..000000000 --- a/docs/types/MysqlQueryResult.html +++ /dev/null @@ -1,431 +0,0 @@ -MysqlQueryResult | kysely
-
- -
-
-
-
- -

Type alias MysqlQueryResult

-
MysqlQueryResult: MysqlOkPacket | ShallowRecord<string, unknown>[]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/NoResultErrorConstructor.html b/docs/types/NoResultErrorConstructor.html deleted file mode 100644 index 5dfddf5b9..000000000 --- a/docs/types/NoResultErrorConstructor.html +++ /dev/null @@ -1,444 +0,0 @@ -NoResultErrorConstructor | kysely
-
- -
-
-
-
- -

Type alias NoResultErrorConstructor

-
NoResultErrorConstructor: (new (node: QueryNode) => Error)
-
-

Type declaration

-
    -
  • -
      -
    • new (node: QueryNode): Error
    • -
    • -
      -

      Parameters

      -
        -
      • -
        node: QueryNode
      -

      Returns Error

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/NonNullableInsertKeys.html b/docs/types/NonNullableInsertKeys.html deleted file mode 100644 index 0a7e91ed9..000000000 --- a/docs/types/NonNullableInsertKeys.html +++ /dev/null @@ -1,438 +0,0 @@ -NonNullableInsertKeys | kysely
-
- -
-
-
-
- -

Type alias NonNullableInsertKeys<R>

-
NonNullableInsertKeys<R>: { [ K in keyof R]: IfNotNullable<InsertType<R[K]>, K> }[keyof R]
-

Keys of R whose InsertType values can't be null or undefined.

-
-
-

Type Parameters

-
    -
  • -

    R

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/NullableInsertKeys.html b/docs/types/NullableInsertKeys.html deleted file mode 100644 index 348407f1f..000000000 --- a/docs/types/NullableInsertKeys.html +++ /dev/null @@ -1,438 +0,0 @@ -NullableInsertKeys | kysely
-
- -
-
-
-
- -

Type alias NullableInsertKeys<R>

-
NullableInsertKeys<R>: { [ K in keyof R]: IfNullable<InsertType<R[K]>, K> }[keyof R]
-

Keys of R whose InsertType values can be null or undefined.

-
-
-

Type Parameters

-
    -
  • -

    R

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/OnCommitAction.html b/docs/types/OnCommitAction.html deleted file mode 100644 index b1a61fa15..000000000 --- a/docs/types/OnCommitAction.html +++ /dev/null @@ -1,431 +0,0 @@ -OnCommitAction | kysely
-
- -
-
-
-
- -

Type alias OnCommitAction

-
OnCommitAction: ArrayItemType<typeof ON_COMMIT_ACTIONS>
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/OnConflictDatabase.html b/docs/types/OnConflictDatabase.html deleted file mode 100644 index 0b8cda7bb..000000000 --- a/docs/types/OnConflictDatabase.html +++ /dev/null @@ -1,438 +0,0 @@ -OnConflictDatabase | kysely
-
- -
-
-
-
- -

Type alias OnConflictDatabase<DB, TB>

-
OnConflictDatabase<DB, TB>: { [ K in keyof DB | "excluded"]: K extends keyof DB ? DB[K] : DB[TB] }
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/OnConflictNodeProps.html b/docs/types/OnConflictNodeProps.html deleted file mode 100644 index d49131947..000000000 --- a/docs/types/OnConflictNodeProps.html +++ /dev/null @@ -1,431 +0,0 @@ -OnConflictNodeProps | kysely
-
- -
-
-
-
- -

Type alias OnConflictNodeProps

-
OnConflictNodeProps: Omit<OnConflictNode, "kind" | "indexWhere" | "updateWhere">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/OnConflictTables.html b/docs/types/OnConflictTables.html deleted file mode 100644 index 386ab5732..000000000 --- a/docs/types/OnConflictTables.html +++ /dev/null @@ -1,436 +0,0 @@ -OnConflictTables | kysely
-
- -
-
-
-
- -

Type alias OnConflictTables<TB>

-
OnConflictTables<TB>: TB | "excluded"
-
-

Type Parameters

-
    -
  • -

    TB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/OnDuplicateKeyNodeProps.html b/docs/types/OnDuplicateKeyNodeProps.html deleted file mode 100644 index 32f3f47c5..000000000 --- a/docs/types/OnDuplicateKeyNodeProps.html +++ /dev/null @@ -1,431 +0,0 @@ -OnDuplicateKeyNodeProps | kysely
-
- -
-
-
-
- -

Type alias OnDuplicateKeyNodeProps

-
OnDuplicateKeyNodeProps: Omit<OnDuplicateKeyNode, "kind">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/OnModifyForeignAction.html b/docs/types/OnModifyForeignAction.html deleted file mode 100644 index 5345c3ae5..000000000 --- a/docs/types/OnModifyForeignAction.html +++ /dev/null @@ -1,431 +0,0 @@ -OnModifyForeignAction | kysely
-
- -
-
-
-
- -

Type alias OnModifyForeignAction

-
OnModifyForeignAction: ArrayItemType<typeof ON_MODIFY_FOREIGN_ACTIONS>
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/OperandValueExpression.html b/docs/types/OperandValueExpression.html deleted file mode 100644 index 0d6cc91da..000000000 --- a/docs/types/OperandValueExpression.html +++ /dev/null @@ -1,440 +0,0 @@ -OperandValueExpression | kysely
-
- -
-
-
-
- -

Type alias OperandValueExpression<DB, TB, RE>

-
OperandValueExpression<DB, TB, RE>: ValueExpression<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, RE>>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    RE

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/OperandValueExpressionOrList.html b/docs/types/OperandValueExpressionOrList.html deleted file mode 100644 index de1d2e060..000000000 --- a/docs/types/OperandValueExpressionOrList.html +++ /dev/null @@ -1,440 +0,0 @@ -OperandValueExpressionOrList | kysely
-
- -
-
-
-
- -

Type alias OperandValueExpressionOrList<DB, TB, RE>

-
OperandValueExpressionOrList<DB, TB, RE>: ValueExpressionOrList<DB, TB, ExtractTypeFromReferenceExpression<DB, TB, RE> | null>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    RE

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/OperationNodeKind.html b/docs/types/OperationNodeKind.html deleted file mode 100644 index 1ccd03e4e..000000000 --- a/docs/types/OperationNodeKind.html +++ /dev/null @@ -1,431 +0,0 @@ -OperationNodeKind | kysely
-
- -
-
-
-
- -

Type alias OperationNodeKind

-
OperationNodeKind: "IdentifierNode" | "SchemableIdentifierNode" | "RawNode" | "SelectQueryNode" | "SelectionNode" | "ReferenceNode" | "ColumnNode" | "TableNode" | "AliasNode" | "FromNode" | "SelectAllNode" | "AndNode" | "OrNode" | "ParensNode" | "ValueNode" | "ValueListNode" | "PrimitiveValueListNode" | "JoinNode" | "OperatorNode" | "WhereNode" | "InsertQueryNode" | "DeleteQueryNode" | "ReturningNode" | "CreateTableNode" | "ColumnDefinitionNode" | "AddColumnNode" | "DropTableNode" | "DataTypeNode" | "OrderByNode" | "OrderByItemNode" | "GroupByNode" | "GroupByItemNode" | "UpdateQueryNode" | "ColumnUpdateNode" | "LimitNode" | "OffsetNode" | "OnConflictNode" | "OnDuplicateKeyNode" | "CreateIndexNode" | "DropIndexNode" | "ListNode" | "ReferencesNode" | "PrimaryKeyConstraintNode" | "UniqueConstraintNode" | "CheckConstraintNode" | "ForeignKeyConstraintNode" | "WithNode" | "CommonTableExpressionNode" | "HavingNode" | "CreateSchemaNode" | "DropSchemaNode" | "AlterTableNode" | "ModifyColumnNode" | "DropColumnNode" | "RenameColumnNode" | "AlterColumnNode" | "AddConstraintNode" | "DropConstraintNode" | "CreateViewNode" | "DropViewNode" | "GeneratedNode" | "DefaultValueNode" | "OnNode" | "ValuesNode" | "CommonTableExpressionNameNode" | "SelectModifierNode" | "CreateTypeNode" | "DropTypeNode" | "ExplainNode" | "DefaultInsertValueNode" | "AggregateFunctionNode" | "OverNode" | "PartitionByNode" | "PartitionByItemNode" | "SetOperationNode" | "BinaryOperationNode" | "UnaryOperationNode" | "UsingNode" | "FunctionNode" | "CaseNode" | "WhenNode"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/Operator.html b/docs/types/Operator.html deleted file mode 100644 index 6f06b45c4..000000000 --- a/docs/types/Operator.html +++ /dev/null @@ -1,431 +0,0 @@ -Operator | kysely
-
- -
-
-
-
- -

Type alias Operator

-
Operator: typeof OPERATORS[number]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/OrderByDirectionExpression.html b/docs/types/OrderByDirectionExpression.html deleted file mode 100644 index bc774f406..000000000 --- a/docs/types/OrderByDirectionExpression.html +++ /dev/null @@ -1,431 +0,0 @@ -OrderByDirectionExpression | kysely
-
- -
-
-
-
- -

Type alias OrderByDirectionExpression

-
OrderByDirectionExpression: OrderByDirection | Expression<any>
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/OrderByExpression.html b/docs/types/OrderByExpression.html deleted file mode 100644 index d0b87ed40..000000000 --- a/docs/types/OrderByExpression.html +++ /dev/null @@ -1,440 +0,0 @@ -OrderByExpression | kysely
-
- -
-
-
-
- -

Type alias OrderByExpression<DB, TB, O>

-
OrderByExpression<DB, TB, O>: ReferenceExpression<DB, TB> | keyof O & string
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    O

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/OverBuilderCallback.html b/docs/types/OverBuilderCallback.html deleted file mode 100644 index aeebb4115..000000000 --- a/docs/types/OverBuilderCallback.html +++ /dev/null @@ -1,451 +0,0 @@ -OverBuilderCallback | kysely
-
- -
-
-
-
- -

Type alias OverBuilderCallback<DB, TB>

-
OverBuilderCallback<DB, TB>: ((builder: OverBuilder<DB, TB>) => OverBuilder<DB, TB>)
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-

Type declaration

-
    -
  • -
      -
    • (builder: OverBuilder<DB, TB>): OverBuilder<DB, TB>
    • -
    • -
      -

      Parameters

      -
        -
      • -
        builder: OverBuilder<DB, TB>
      -

      Returns OverBuilder<DB, TB>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/PostgresCursorConstructor.html b/docs/types/PostgresCursorConstructor.html deleted file mode 100644 index 15eb3a923..000000000 --- a/docs/types/PostgresCursorConstructor.html +++ /dev/null @@ -1,451 +0,0 @@ -PostgresCursorConstructor | kysely
-
- -
-
-
-
- -

Type alias PostgresCursorConstructor

-
PostgresCursorConstructor: (new <T>(sql: string, parameters: unknown[]) => PostgresCursor<T>)
-
-

Type declaration

-
    -
  • -
      -
    • new <T>(sql: string, parameters: unknown[]): PostgresCursor<T>
    • -
    • -
      -

      Type Parameters

      -
        -
      • -

        T

      -
      -

      Parameters

      -
        -
      • -
        sql: string
      • -
      • -
        parameters: unknown[]
      -

      Returns PostgresCursor<T>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/QueryNode.html b/docs/types/QueryNode.html deleted file mode 100644 index e649d3cad..000000000 --- a/docs/types/QueryNode.html +++ /dev/null @@ -1,432 +0,0 @@ -QueryNode | kysely
-
- -
-
-
-
- -

Type alias QueryNode

-
QueryNode: SelectQueryNode | InsertQueryNode | UpdateQueryNode | DeleteQueryNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ReferenceExpression.html b/docs/types/ReferenceExpression.html deleted file mode 100644 index ea1e611f1..000000000 --- a/docs/types/ReferenceExpression.html +++ /dev/null @@ -1,438 +0,0 @@ -ReferenceExpression | kysely
-
- -
-
-
-
- -

Type alias ReferenceExpression<DB, TB>

-
ReferenceExpression<DB, TB>: SimpleReferenceExpression<DB, TB> | ExpressionOrFactory<DB, TB, any>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ReferenceExpressionOrList.html b/docs/types/ReferenceExpressionOrList.html deleted file mode 100644 index ede9146b6..000000000 --- a/docs/types/ReferenceExpressionOrList.html +++ /dev/null @@ -1,438 +0,0 @@ -ReferenceExpressionOrList | kysely
-
- -
-
-
-
- -

Type alias ReferenceExpressionOrList<DB, TB>

-
ReferenceExpressionOrList<DB, TB>: ReferenceExpression<DB, TB> | ReadonlyArray<ReferenceExpression<DB, TB>>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/RootOperationNode.html b/docs/types/RootOperationNode.html deleted file mode 100644 index 007ffc164..000000000 --- a/docs/types/RootOperationNode.html +++ /dev/null @@ -1,431 +0,0 @@ -RootOperationNode | kysely
-
- -
-
-
-
- -

Type alias RootOperationNode

-
RootOperationNode: QueryNode | CreateTableNode | CreateIndexNode | CreateSchemaNode | CreateViewNode | DropTableNode | DropIndexNode | DropSchemaNode | DropViewNode | AlterTableNode | RawNode | CreateTypeNode | DropTypeNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/SelectArg.html b/docs/types/SelectArg.html deleted file mode 100644 index 3c1a1ffd3..000000000 --- a/docs/types/SelectArg.html +++ /dev/null @@ -1,440 +0,0 @@ -SelectArg | kysely
-
- -
-
-
-
- -

Type alias SelectArg<DB, TB, SE>

-
SelectArg<DB, TB, SE>: SE | ReadonlyArray<SE> | ((eb: ExpressionBuilder<DB, TB>) => ReadonlyArray<SE>)
-
-

Type Parameters

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/SelectExpression.html b/docs/types/SelectExpression.html deleted file mode 100644 index 5aa2d3436..000000000 --- a/docs/types/SelectExpression.html +++ /dev/null @@ -1,438 +0,0 @@ -SelectExpression | kysely
-
- -
-
-
-
- -

Type alias SelectExpression<DB, TB>

-
SelectExpression<DB, TB>: AnyAliasedColumnWithTable<DB, TB> | AnyAliasedColumn<DB, TB> | AnyColumnWithTable<DB, TB> | AnyColumn<DB, TB> | DynamicReferenceBuilder<any> | AliasedExpressionOrFactory<DB, TB>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/SelectQueryBuilderWithFullJoin.html b/docs/types/SelectQueryBuilderWithFullJoin.html deleted file mode 100644 index 8c702d3d1..000000000 --- a/docs/types/SelectQueryBuilderWithFullJoin.html +++ /dev/null @@ -1,442 +0,0 @@ -SelectQueryBuilderWithFullJoin | kysely
-
- -
-
-
-
- -

Type alias SelectQueryBuilderWithFullJoin<DB, TB, O, TE>

-
SelectQueryBuilderWithFullJoin<DB, TB, O, TE>: TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? OuterJoinedBuilder<DB, TB, O, A, DB[T]> : never : TE extends keyof DB ? OuterJoinedBuilder<DB, TB, O, TE, DB[TE]> : TE extends AliasedExpression<infer QO, infer QA> ? OuterJoinedBuilder<DB, TB, O, QA, QO> : TE extends ((qb: any) => AliasedExpression<infer QO, infer QA>) ? OuterJoinedBuilder<DB, TB, O, QA, QO> : never
-
-

Type Parameters

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/SelectQueryBuilderWithInnerJoin.html b/docs/types/SelectQueryBuilderWithInnerJoin.html deleted file mode 100644 index 21cbd0202..000000000 --- a/docs/types/SelectQueryBuilderWithInnerJoin.html +++ /dev/null @@ -1,442 +0,0 @@ -SelectQueryBuilderWithInnerJoin | kysely
-
- -
-
-
-
- -

Type alias SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>

-
SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>: TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? InnerJoinedBuilder<DB, TB, O, A, DB[T]> : never : TE extends keyof DB ? SelectQueryBuilder<DB, TB | TE, O> : TE extends AliasedExpression<infer QO, infer QA> ? InnerJoinedBuilder<DB, TB, O, QA, QO> : TE extends ((qb: any) => AliasedExpression<infer QO, infer QA>) ? InnerJoinedBuilder<DB, TB, O, QA, QO> : never
-
-

Type Parameters

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/SelectQueryBuilderWithLeftJoin.html b/docs/types/SelectQueryBuilderWithLeftJoin.html deleted file mode 100644 index 0b1d68148..000000000 --- a/docs/types/SelectQueryBuilderWithLeftJoin.html +++ /dev/null @@ -1,442 +0,0 @@ -SelectQueryBuilderWithLeftJoin | kysely
-
- -
-
-
-
- -

Type alias SelectQueryBuilderWithLeftJoin<DB, TB, O, TE>

-
SelectQueryBuilderWithLeftJoin<DB, TB, O, TE>: TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? LeftJoinedBuilder<DB, TB, O, A, DB[T]> : never : TE extends keyof DB ? LeftJoinedBuilder<DB, TB, O, TE, DB[TE]> : TE extends AliasedExpression<infer QO, infer QA> ? LeftJoinedBuilder<DB, TB, O, QA, QO> : TE extends ((qb: any) => AliasedExpression<infer QO, infer QA>) ? LeftJoinedBuilder<DB, TB, O, QA, QO> : never
-
-

Type Parameters

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/SelectQueryBuilderWithRightJoin.html b/docs/types/SelectQueryBuilderWithRightJoin.html deleted file mode 100644 index 9d2451cfb..000000000 --- a/docs/types/SelectQueryBuilderWithRightJoin.html +++ /dev/null @@ -1,442 +0,0 @@ -SelectQueryBuilderWithRightJoin | kysely
-
- -
-
-
-
- -

Type alias SelectQueryBuilderWithRightJoin<DB, TB, O, TE>

-
SelectQueryBuilderWithRightJoin<DB, TB, O, TE>: TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? RightJoinedBuilder<DB, TB, O, A, DB[T]> : never : TE extends keyof DB ? RightJoinedBuilder<DB, TB, O, TE, DB[TE]> : TE extends AliasedExpression<infer QO, infer QA> ? RightJoinedBuilder<DB, TB, O, QA, QO> : TE extends ((qb: any) => AliasedExpression<infer QO, infer QA>) ? RightJoinedBuilder<DB, TB, O, QA, QO> : never
-
-

Type Parameters

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/SelectType.html b/docs/types/SelectType.html deleted file mode 100644 index c4b470cd5..000000000 --- a/docs/types/SelectType.html +++ /dev/null @@ -1,436 +0,0 @@ -SelectType | kysely
-
- -
-
-
-
- -

Type alias SelectType<T>

-
SelectType<T>: T extends ColumnType<infer S, any, any> ? S : T
-
-

Type Parameters

-
    -
  • -

    T

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/Selectable.html b/docs/types/Selectable.html deleted file mode 100644 index 8b394cc1f..000000000 --- a/docs/types/Selectable.html +++ /dev/null @@ -1,445 +0,0 @@ -Selectable | kysely
-
- -
-
-
-
- -

Type alias Selectable<R>

-
Selectable<R>: DrainOuterGeneric<{ [ K in NonNeverSelectKeys<R>]: SelectType<R[K]> }>
-

Given a table interface, extracts the select type from all -ColumnType types.

- - -

Examples

-
-
interface PersonTable {
id: Generated<number>
first_name: string
modified_at: ColumnType<Date, string, never>
}

type Person = Selectable<PersonTable>
// {
// id: number,
// first_name: string
// modified_at: Date
// } -
-
-
-

Type Parameters

-
    -
  • -

    R

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/Selection.html b/docs/types/Selection.html deleted file mode 100644 index 17711afe0..000000000 --- a/docs/types/Selection.html +++ /dev/null @@ -1,440 +0,0 @@ -Selection | kysely
-
- -
-
-
-
- -

Type alias Selection<DB, TB, SE>

-
Selection<DB, TB, SE>: DrainOuterGeneric<{ [ A in ExtractAliasFromSelectExpression<SE>]: SelectType<ExtractTypeFromSelectExpression<DB, TB, SE, A>> }>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    SE

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/SetOperator.html b/docs/types/SetOperator.html deleted file mode 100644 index 0b0c47313..000000000 --- a/docs/types/SetOperator.html +++ /dev/null @@ -1,431 +0,0 @@ -SetOperator | kysely
-
- -
-
-
-
- -

Type alias SetOperator

-
SetOperator: "union" | "intersect" | "except"
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/SimpleReferenceExpression.html b/docs/types/SimpleReferenceExpression.html deleted file mode 100644 index 299371fdc..000000000 --- a/docs/types/SimpleReferenceExpression.html +++ /dev/null @@ -1,438 +0,0 @@ -SimpleReferenceExpression | kysely
-
- -
-
-
-
- -

Type alias SimpleReferenceExpression<DB, TB>

-
SimpleReferenceExpression<DB, TB>: StringReference<DB, TB> | DynamicReferenceBuilder<any>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/Simplify.html b/docs/types/Simplify.html deleted file mode 100644 index b2eadb30f..000000000 --- a/docs/types/Simplify.html +++ /dev/null @@ -1,436 +0,0 @@ -Simplify | kysely
-
- -
-
-
-
- -

Type alias Simplify<T>

-
Simplify<T>: DrainOuterGeneric<{ [ K in keyof T]: T[K] } & {}>
-
-

Type Parameters

-
    -
  • -

    T

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/SqlBool.html b/docs/types/SqlBool.html deleted file mode 100644 index 293294e43..000000000 --- a/docs/types/SqlBool.html +++ /dev/null @@ -1,431 +0,0 @@ -SqlBool | kysely
-
- -
-
-
-
- -

Type alias SqlBool

-
SqlBool: boolean | 0 | 1
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/StringReference.html b/docs/types/StringReference.html deleted file mode 100644 index fbdeb7b7e..000000000 --- a/docs/types/StringReference.html +++ /dev/null @@ -1,438 +0,0 @@ -StringReference | kysely
-
- -
-
-
-
- -

Type alias StringReference<DB, TB>

-
StringReference<DB, TB>: AnyColumn<DB, TB> | AnyColumnWithTable<DB, TB>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/TableExpression.html b/docs/types/TableExpression.html deleted file mode 100644 index da7455549..000000000 --- a/docs/types/TableExpression.html +++ /dev/null @@ -1,438 +0,0 @@ -TableExpression | kysely
-
- -
-
-
-
- -

Type alias TableExpression<DB, TB>

-
TableExpression<DB, TB>: AnyAliasedTable<DB> | AnyTable<DB> | AliasedExpressionOrFactory<DB, TB>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/TableExpressionOrList.html b/docs/types/TableExpressionOrList.html deleted file mode 100644 index c7b4ae8e8..000000000 --- a/docs/types/TableExpressionOrList.html +++ /dev/null @@ -1,438 +0,0 @@ -TableExpressionOrList | kysely
-
- -
-
-
-
- -

Type alias TableExpressionOrList<DB, TB>

-
TableExpressionOrList<DB, TB>: TableExpression<DB, TB> | ReadonlyArray<TableExpression<DB, TB>>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/UnaryFilterOperator.html b/docs/types/UnaryFilterOperator.html deleted file mode 100644 index 15b585c9a..000000000 --- a/docs/types/UnaryFilterOperator.html +++ /dev/null @@ -1,431 +0,0 @@ -UnaryFilterOperator | kysely
-
- -
-
-
-
- -

Type alias UnaryFilterOperator

-
UnaryFilterOperator: typeof UNARY_FILTER_OPERATORS[number]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/UnaryOperator.html b/docs/types/UnaryOperator.html deleted file mode 100644 index a222c27b7..000000000 --- a/docs/types/UnaryOperator.html +++ /dev/null @@ -1,431 +0,0 @@ -UnaryOperator | kysely
-
- -
-
-
-
- -

Type alias UnaryOperator

-
UnaryOperator: typeof UNARY_OPERATORS[number]
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/UnknownRow.html b/docs/types/UnknownRow.html deleted file mode 100644 index ce73e7128..000000000 --- a/docs/types/UnknownRow.html +++ /dev/null @@ -1,433 +0,0 @@ -UnknownRow | kysely
-
- -
-
-
-
- -

Type alias UnknownRow

-
UnknownRow: Record<string, unknown>
-

Represents a database row whose column names and their types are unknown.

-
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/UpdateKeys.html b/docs/types/UpdateKeys.html deleted file mode 100644 index bba527e3f..000000000 --- a/docs/types/UpdateKeys.html +++ /dev/null @@ -1,438 +0,0 @@ -UpdateKeys | kysely
-
- -
-
-
-
- -

Type alias UpdateKeys<R>

-
UpdateKeys<R>: { [ K in keyof R]: IfNotNever<UpdateType<R[K]>, K> }[keyof R]
-

Keys of R whose UpdateType values are not never

-
-
-

Type Parameters

-
    -
  • -

    R

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/UpdateObject.html b/docs/types/UpdateObject.html deleted file mode 100644 index 02e79d256..000000000 --- a/docs/types/UpdateObject.html +++ /dev/null @@ -1,440 +0,0 @@ -UpdateObject | kysely
-
- -
-
-
-
- -

Type alias UpdateObject<DB, TB, UT>

-
UpdateObject<DB, TB, UT>: { [ C in UpdateKeys<DB[UT]>]?: ValueExpression<DB, TB, UpdateType<DB[UT][C]>> }
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    UT extends keyof DB = TB

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/UpdateQueryBuilderWithFullJoin.html b/docs/types/UpdateQueryBuilderWithFullJoin.html deleted file mode 100644 index 1523b0f7a..000000000 --- a/docs/types/UpdateQueryBuilderWithFullJoin.html +++ /dev/null @@ -1,444 +0,0 @@ -UpdateQueryBuilderWithFullJoin | kysely
-
- -
-
-
-
- -

Type alias UpdateQueryBuilderWithFullJoin<DB, UT, TB, O, TE>

-
UpdateQueryBuilderWithFullJoin<DB, UT, TB, O, TE>: TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? OuterJoinedBuilder<DB, UT, TB, O, A, DB[T]> : never : TE extends keyof DB ? OuterJoinedBuilder<DB, UT, TB, O, TE, DB[TE]> : TE extends AliasedExpression<infer QO, infer QA> ? OuterJoinedBuilder<DB, UT, TB, O, QA, QO> : TE extends ((qb: any) => AliasedExpression<infer QO, infer QA>) ? OuterJoinedBuilder<DB, UT, TB, O, QA, QO> : never
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    UT extends keyof DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    O

  • -
  • -

    TE extends TableExpression<DB, TB>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/UpdateQueryBuilderWithInnerJoin.html b/docs/types/UpdateQueryBuilderWithInnerJoin.html deleted file mode 100644 index 628a8ada3..000000000 --- a/docs/types/UpdateQueryBuilderWithInnerJoin.html +++ /dev/null @@ -1,444 +0,0 @@ -UpdateQueryBuilderWithInnerJoin | kysely
-
- -
-
-
-
- -

Type alias UpdateQueryBuilderWithInnerJoin<DB, UT, TB, O, TE>

-
UpdateQueryBuilderWithInnerJoin<DB, UT, TB, O, TE>: TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? InnerJoinedBuilder<DB, UT, TB, O, A, DB[T]> : never : TE extends keyof DB ? UpdateQueryBuilder<DB, UT, TB | TE, O> : TE extends AliasedExpression<infer QO, infer QA> ? InnerJoinedBuilder<DB, UT, TB, O, QA, QO> : TE extends ((qb: any) => AliasedExpression<infer QO, infer QA>) ? InnerJoinedBuilder<DB, UT, TB, O, QA, QO> : never
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    UT extends keyof DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    O

  • -
  • -

    TE extends TableExpression<DB, TB>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/UpdateQueryBuilderWithLeftJoin.html b/docs/types/UpdateQueryBuilderWithLeftJoin.html deleted file mode 100644 index 4b21dc6c8..000000000 --- a/docs/types/UpdateQueryBuilderWithLeftJoin.html +++ /dev/null @@ -1,444 +0,0 @@ -UpdateQueryBuilderWithLeftJoin | kysely
-
- -
-
-
-
- -

Type alias UpdateQueryBuilderWithLeftJoin<DB, UT, TB, O, TE>

-
UpdateQueryBuilderWithLeftJoin<DB, UT, TB, O, TE>: TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? LeftJoinedBuilder<DB, UT, TB, O, A, DB[T]> : never : TE extends keyof DB ? LeftJoinedBuilder<DB, UT, TB, O, TE, DB[TE]> : TE extends AliasedExpression<infer QO, infer QA> ? LeftJoinedBuilder<DB, UT, TB, O, QA, QO> : TE extends ((qb: any) => AliasedExpression<infer QO, infer QA>) ? LeftJoinedBuilder<DB, UT, TB, O, QA, QO> : never
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    UT extends keyof DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    O

  • -
  • -

    TE extends TableExpression<DB, TB>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/UpdateQueryBuilderWithRightJoin.html b/docs/types/UpdateQueryBuilderWithRightJoin.html deleted file mode 100644 index 2e9210819..000000000 --- a/docs/types/UpdateQueryBuilderWithRightJoin.html +++ /dev/null @@ -1,444 +0,0 @@ -UpdateQueryBuilderWithRightJoin | kysely
-
- -
-
-
-
- -

Type alias UpdateQueryBuilderWithRightJoin<DB, UT, TB, O, TE>

-
UpdateQueryBuilderWithRightJoin<DB, UT, TB, O, TE>: TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? RightJoinedBuilder<DB, UT, TB, O, A, DB[T]> : never : TE extends keyof DB ? RightJoinedBuilder<DB, UT, TB, O, TE, DB[TE]> : TE extends AliasedExpression<infer QO, infer QA> ? RightJoinedBuilder<DB, UT, TB, O, QA, QO> : TE extends ((qb: any) => AliasedExpression<infer QO, infer QA>) ? RightJoinedBuilder<DB, UT, TB, O, QA, QO> : never
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    UT extends keyof DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    O

  • -
  • -

    TE extends TableExpression<DB, TB>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/UpdateType.html b/docs/types/UpdateType.html deleted file mode 100644 index aa15b9bfc..000000000 --- a/docs/types/UpdateType.html +++ /dev/null @@ -1,436 +0,0 @@ -UpdateType | kysely
-
- -
-
-
-
- -

Type alias UpdateType<T>

-
UpdateType<T>: T extends ColumnType<any, any, infer U> ? U : T
-
-

Type Parameters

-
    -
  • -

    T

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/UpdateValuesNode.html b/docs/types/UpdateValuesNode.html deleted file mode 100644 index e5ef68d69..000000000 --- a/docs/types/UpdateValuesNode.html +++ /dev/null @@ -1,431 +0,0 @@ -UpdateValuesNode | kysely
-
- -
-
-
-
- -

Type alias UpdateValuesNode

-
UpdateValuesNode: ValueListNode | PrimitiveValueListNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/Updateable.html b/docs/types/Updateable.html deleted file mode 100644 index a5459c853..000000000 --- a/docs/types/Updateable.html +++ /dev/null @@ -1,445 +0,0 @@ -Updateable | kysely
-
- -
-
-
-
- -

Type alias Updateable<R>

-
Updateable<R>: { [ K in UpdateKeys<R>]?: UpdateType<R[K]> }
-

Given a table interface, extracts the update type from all -ColumnType types.

- - -

Examples

-
-
interface PersonTable {
id: Generated<number>
first_name: string
modified_at: ColumnType<Date, string, never>
}

type UpdateablePerson = Updateable<PersonTable>
// {
// id?: number,
// first_name?: string
// } -
-
-
-

Type Parameters

-
    -
  • -

    R

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ValueExpression.html b/docs/types/ValueExpression.html deleted file mode 100644 index 4ce4e8770..000000000 --- a/docs/types/ValueExpression.html +++ /dev/null @@ -1,440 +0,0 @@ -ValueExpression | kysely
-
- -
-
-
-
- -

Type alias ValueExpression<DB, TB, V>

-
ValueExpression<DB, TB, V>: V | ExpressionOrFactory<DB, TB, V>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    V

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ValueExpressionOrList.html b/docs/types/ValueExpressionOrList.html deleted file mode 100644 index 59413b9a7..000000000 --- a/docs/types/ValueExpressionOrList.html +++ /dev/null @@ -1,440 +0,0 @@ -ValueExpressionOrList | kysely
-
- -
-
-
-
- -

Type alias ValueExpressionOrList<DB, TB, V>

-
ValueExpressionOrList<DB, TB, V>: ValueExpression<DB, TB, V> | ReadonlyArray<ValueExpression<DB, TB, V>>
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

  • -
  • -

    V

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/ValuesItemNode.html b/docs/types/ValuesItemNode.html deleted file mode 100644 index ce9bdf7bd..000000000 --- a/docs/types/ValuesItemNode.html +++ /dev/null @@ -1,431 +0,0 @@ -ValuesItemNode | kysely
-
- -
-
-
-
- -

Type alias ValuesItemNode

-
ValuesItemNode: ValueListNode | PrimitiveValueListNode
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/WhereExpressionFactory.html b/docs/types/WhereExpressionFactory.html deleted file mode 100644 index b7131a3ef..000000000 --- a/docs/types/WhereExpressionFactory.html +++ /dev/null @@ -1,451 +0,0 @@ -WhereExpressionFactory | kysely
-
- -
-
-
-
- -

Type alias WhereExpressionFactory<DB, TB>

-
WhereExpressionFactory<DB, TB>: ((eb: WhereExpressionBuilder<DB, TB>) => Expression<SqlBool> | WhereExpressionBuilder<DB, TB>)
-
-

Type Parameters

-
    -
  • -

    DB

  • -
  • -

    TB extends keyof DB

-
-

Type declaration

-
    -
  • -
      -
    • (eb: WhereExpressionBuilder<DB, TB>): Expression<SqlBool> | WhereExpressionBuilder<DB, TB>
    • -
    • -
      -

      Parameters

      -
        -
      • -
        eb: WhereExpressionBuilder<DB, TB>
      -

      Returns Expression<SqlBool> | WhereExpressionBuilder<DB, TB>

-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/types/WithNodeParams.html b/docs/types/WithNodeParams.html deleted file mode 100644 index 2a7a1c876..000000000 --- a/docs/types/WithNodeParams.html +++ /dev/null @@ -1,431 +0,0 @@ -WithNodeParams | kysely
-
- -
-
-
-
- -

Type alias WithNodeParams

-
WithNodeParams: Omit<WithNode, "kind" | "expressions">
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/ARITHMETIC_OPERATORS.html b/docs/variables/ARITHMETIC_OPERATORS.html deleted file mode 100644 index 3d2e99e23..000000000 --- a/docs/variables/ARITHMETIC_OPERATORS.html +++ /dev/null @@ -1,431 +0,0 @@ -ARITHMETIC_OPERATORS | kysely
-
- -
-
-
-
- -

Variable ARITHMETIC_OPERATORSConst

-
ARITHMETIC_OPERATORS: readonly ["+", "-", "*", "/", "%", "^", "&", "|", "#", "<<", ">>"] = ...
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/BINARY_OPERATORS.html b/docs/variables/BINARY_OPERATORS.html deleted file mode 100644 index bb2eadd45..000000000 --- a/docs/variables/BINARY_OPERATORS.html +++ /dev/null @@ -1,431 +0,0 @@ -BINARY_OPERATORS | kysely
-
- -
-
-
-
- -

Variable BINARY_OPERATORSConst

-
BINARY_OPERATORS: readonly ["=", "==", "!=", "<>", ">", ">=", "<", "<=", "in", "not in", "is", "is not", "like", "not like", "match", "ilike", "not ilike", "@>", "<@", "?", "?&", "!<", "!>", "<=>", "!~", "~", "~*", "!~*", "@@", "@@@", "!!", "<->", "+", "-", "*", "/", "%", "^", "&", "|", "#", "<<", ">>", "&&", "||"] = ...
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/COMPARISON_OPERATORS.html b/docs/variables/COMPARISON_OPERATORS.html deleted file mode 100644 index 958a3b419..000000000 --- a/docs/variables/COMPARISON_OPERATORS.html +++ /dev/null @@ -1,431 +0,0 @@ -COMPARISON_OPERATORS | kysely
-
- -
-
-
-
- -

Variable COMPARISON_OPERATORSConst

-
COMPARISON_OPERATORS: readonly ["=", "==", "!=", "<>", ">", ">=", "<", "<=", "in", "not in", "is", "is not", "like", "not like", "match", "ilike", "not ilike", "@>", "<@", "?", "?&", "!<", "!>", "<=>", "!~", "~", "~*", "!~*", "@@", "@@@", "!!", "<->"] = ...
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/CompiledQuery-1.html b/docs/variables/CompiledQuery-1.html deleted file mode 100644 index ad0c1d5fc..000000000 --- a/docs/variables/CompiledQuery-1.html +++ /dev/null @@ -1,432 +0,0 @@ -CompiledQuery | kysely
-
- -
-
-
-
- -

Variable CompiledQuery

-
CompiledQuery: Readonly<{
    raw(sql: string): CompiledQuery<unknown>;
}>
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/DEFAULT_MIGRATION_LOCK_TABLE.html b/docs/variables/DEFAULT_MIGRATION_LOCK_TABLE.html deleted file mode 100644 index 558a7823e..000000000 --- a/docs/variables/DEFAULT_MIGRATION_LOCK_TABLE.html +++ /dev/null @@ -1,431 +0,0 @@ -DEFAULT_MIGRATION_LOCK_TABLE | kysely
-
- -
-
-
-
- -

Variable DEFAULT_MIGRATION_LOCK_TABLEConst

-
DEFAULT_MIGRATION_LOCK_TABLE: "kysely_migration_lock" = 'kysely_migration_lock'
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/DEFAULT_MIGRATION_TABLE.html b/docs/variables/DEFAULT_MIGRATION_TABLE.html deleted file mode 100644 index 8e1b46777..000000000 --- a/docs/variables/DEFAULT_MIGRATION_TABLE.html +++ /dev/null @@ -1,431 +0,0 @@ -DEFAULT_MIGRATION_TABLE | kysely
-
- -
-
-
-
- -

Variable DEFAULT_MIGRATION_TABLEConst

-
DEFAULT_MIGRATION_TABLE: "kysely_migration" = 'kysely_migration'
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/LOG_LEVELS.html b/docs/variables/LOG_LEVELS.html deleted file mode 100644 index 837f10ac7..000000000 --- a/docs/variables/LOG_LEVELS.html +++ /dev/null @@ -1,431 +0,0 @@ -LOG_LEVELS | kysely
-
- -
-
-
-
- -

Variable LOG_LEVELSConst

-
LOG_LEVELS: readonly ["query", "error"] = ...
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/MIGRATION_LOCK_ID.html b/docs/variables/MIGRATION_LOCK_ID.html deleted file mode 100644 index d1719f2dc..000000000 --- a/docs/variables/MIGRATION_LOCK_ID.html +++ /dev/null @@ -1,431 +0,0 @@ -MIGRATION_LOCK_ID | kysely
-
- -
-
-
-
- -

Variable MIGRATION_LOCK_IDConst

-
MIGRATION_LOCK_ID: "migration_lock" = 'migration_lock'
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/NOOP_QUERY_EXECUTOR.html b/docs/variables/NOOP_QUERY_EXECUTOR.html deleted file mode 100644 index 7e05b17f2..000000000 --- a/docs/variables/NOOP_QUERY_EXECUTOR.html +++ /dev/null @@ -1,431 +0,0 @@ -NOOP_QUERY_EXECUTOR | kysely
-
- -
-
-
-
- -

Variable NOOP_QUERY_EXECUTORConst

-
NOOP_QUERY_EXECUTOR: NoopQueryExecutor = ...
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/NO_MIGRATIONS.html b/docs/variables/NO_MIGRATIONS.html deleted file mode 100644 index 18962cd97..000000000 --- a/docs/variables/NO_MIGRATIONS.html +++ /dev/null @@ -1,431 +0,0 @@ -NO_MIGRATIONS | kysely
-
- -
-
-
-
- -

Variable NO_MIGRATIONSConst

-
NO_MIGRATIONS: NoMigrations = ...
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/ON_COMMIT_ACTIONS.html b/docs/variables/ON_COMMIT_ACTIONS.html deleted file mode 100644 index d210ee606..000000000 --- a/docs/variables/ON_COMMIT_ACTIONS.html +++ /dev/null @@ -1,431 +0,0 @@ -ON_COMMIT_ACTIONS | kysely
-
- -
-
-
-
- -

Variable ON_COMMIT_ACTIONSConst

-
ON_COMMIT_ACTIONS: string[] = ...
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/ON_MODIFY_FOREIGN_ACTIONS.html b/docs/variables/ON_MODIFY_FOREIGN_ACTIONS.html deleted file mode 100644 index 63a8d3b16..000000000 --- a/docs/variables/ON_MODIFY_FOREIGN_ACTIONS.html +++ /dev/null @@ -1,431 +0,0 @@ -ON_MODIFY_FOREIGN_ACTIONS | kysely
-
- -
-
-
-
- -

Variable ON_MODIFY_FOREIGN_ACTIONSConst

-
ON_MODIFY_FOREIGN_ACTIONS: readonly ["no action", "restrict", "cascade", "set null", "set default"] = ...
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/OPERATORS.html b/docs/variables/OPERATORS.html deleted file mode 100644 index d3760ecd3..000000000 --- a/docs/variables/OPERATORS.html +++ /dev/null @@ -1,431 +0,0 @@ -OPERATORS | kysely
-
- -
-
-
-
- -

Variable OPERATORSConst

-
OPERATORS: readonly ["=", "==", "!=", "<>", ">", ">=", "<", "<=", "in", "not in", "is", "is not", "like", "not like", "match", "ilike", "not ilike", "@>", "<@", "?", "?&", "!<", "!>", "<=>", "!~", "~", "~*", "!~*", "@@", "@@@", "!!", "<->", "+", "-", "*", "/", "%", "^", "&", "|", "#", "<<", ">>", "&&", "||", "not", "-", "exists", "not exists"] = ...
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/TRANSACTION_ISOLATION_LEVELS.html b/docs/variables/TRANSACTION_ISOLATION_LEVELS.html deleted file mode 100644 index f6332c26c..000000000 --- a/docs/variables/TRANSACTION_ISOLATION_LEVELS.html +++ /dev/null @@ -1,431 +0,0 @@ -TRANSACTION_ISOLATION_LEVELS | kysely
-
- -
-
-
-
- -

Variable TRANSACTION_ISOLATION_LEVELSConst

-
TRANSACTION_ISOLATION_LEVELS: readonly ["read uncommitted", "read committed", "repeatable read", "serializable"] = ...
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/UNARY_FILTER_OPERATORS.html b/docs/variables/UNARY_FILTER_OPERATORS.html deleted file mode 100644 index c8bcaabc0..000000000 --- a/docs/variables/UNARY_FILTER_OPERATORS.html +++ /dev/null @@ -1,431 +0,0 @@ -UNARY_FILTER_OPERATORS | kysely
-
- -
-
-
-
- -

Variable UNARY_FILTER_OPERATORSConst

-
UNARY_FILTER_OPERATORS: readonly ["exists", "not exists"] = ...
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/variables/UNARY_OPERATORS.html b/docs/variables/UNARY_OPERATORS.html deleted file mode 100644 index d76691af2..000000000 --- a/docs/variables/UNARY_OPERATORS.html +++ /dev/null @@ -1,431 +0,0 @@ -UNARY_OPERATORS | kysely
-
- -
-
-
-
- -

Variable UNARY_OPERATORSConst

-
UNARY_OPERATORS: readonly ["not", "-", "exists", "not exists"] = ...
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a9f7b324f..965f7e86f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,73 +1,430 @@ { "name": "kysely", - "version": "0.25.0", + "version": "0.27.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "kysely", - "version": "0.25.0", + "version": "0.27.3", "license": "MIT", "devDependencies": { - "@types/better-sqlite3": "^7.6.4", - "@types/chai": "^4.3.5", - "@types/chai-as-promised": "^7.1.5", - "@types/chai-subset": "^1.3.3", - "@types/mocha": "^10.0.1", + "@types/better-sqlite3": "^7.6.8", + "@types/chai": "^4.3.11", + "@types/chai-as-promised": "^7.1.8", + "@types/chai-subset": "^1.3.5", + "@types/mocha": "^10.0.6", "@types/node": "^18.15.11", - "@types/pg": "^8.10.2", - "@types/pg-cursor": "^2.7.0", - "@types/sinon": "^10.0.15", - "better-sqlite3": "^8.4.0", - "chai": "^4.3.7", + "@types/pg": "^8.10.9", + "@types/pg-cursor": "^2.7.2", + "@types/sinon": "^17.0.2", + "@types/tedious": "^4.0.9", + "better-sqlite3": "^9.2.2", + "chai": "^4.4.0", "chai-as-promised": "^7.1.1", "chai-subset": "^1.6.0", - "concurrently": "^8.1.0", - "esbuild": "^0.17.19", + "esbuild": "^0.19.11", + "lodash": "^4.17.21", "mocha": "^10.2.0", - "mysql2": "^3.3.3", - "pg": "^8.11.0", - "pg-cursor": "^2.10.0", - "playwright": "^1.34.3", - "prettier": "^2.8.8", - "sinon": "^15.1.0", - "tsd": "^0.28.1", - "typedoc": "^0.24.8", - "typescript": "5.1.3" + "mysql2": "^3.6.5", + "pg": "^8.11.3", + "pg-cursor": "^2.10.3", + "playwright": "^1.40.1", + "prettier": "^3.1.1", + "sinon": "^17.0.1", + "tarn": "^3.0.2", + "tedious": "^16.4.0", + "tsd": "^0.30.3", + "typescript": "^5.4.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@azure/abort-controller": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", + "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", + "dev": true, + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@azure/core-auth": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.6.0.tgz", + "integrity": "sha512-3X9wzaaGgRaBCwhLQZDtFp5uLIXCPrGbwJNWPPugvL4xbIGgScv77YzzxToKGLAKvG9amDoofMoP+9hsH1vs1w==", + "dev": true, + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-util": "^1.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-auth/node_modules/@azure/abort-controller": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.0.0.tgz", + "integrity": "sha512-RP/mR/WJchR+g+nQFJGOec+nzeN/VvjlwbinccoqfhTsTHbb8X5+mLDp48kHT0ueyum0BNSwGm0kX0UZuIqTGg==", + "dev": true, + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-client": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.8.0.tgz", + "integrity": "sha512-+gHS3gEzPlhyQBMoqVPOTeNH031R5DM/xpCvz72y38C09rg4Hui/1sJS/ujoisDZbbSHyuRLVWdFlwL0pIFwbg==", + "dev": true, + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.4.0", + "@azure/core-rest-pipeline": "^1.9.1", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.0.0", + "@azure/logger": "^1.0.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-client/node_modules/@azure/abort-controller": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.0.0.tgz", + "integrity": "sha512-RP/mR/WJchR+g+nQFJGOec+nzeN/VvjlwbinccoqfhTsTHbb8X5+mLDp48kHT0ueyum0BNSwGm0kX0UZuIqTGg==", + "dev": true, + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-http-compat": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.0.1.tgz", + "integrity": "sha512-xpQZz/q7E0jSW4rckrTo2mDFDQgo6I69hBU4voMQi7REi6JRW5a+KfVkbJCFCWnkFmP6cAJ0IbuudTdf/MEBOQ==", + "dev": true, + "dependencies": { + "@azure/abort-controller": "^1.0.4", + "@azure/core-client": "^1.3.0", + "@azure/core-rest-pipeline": "^1.3.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@azure/core-lro": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.6.0.tgz", + "integrity": "sha512-PyRNcaIOfMgoUC01/24NoG+k8O81VrKxYARnDlo+Q2xji0/0/j2nIt8BwQh294pb1c5QnXTDPbNR4KzoDKXEoQ==", + "dev": true, + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-util": "^1.2.0", + "@azure/logger": "^1.0.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-lro/node_modules/@azure/abort-controller": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.0.0.tgz", + "integrity": "sha512-RP/mR/WJchR+g+nQFJGOec+nzeN/VvjlwbinccoqfhTsTHbb8X5+mLDp48kHT0ueyum0BNSwGm0kX0UZuIqTGg==", + "dev": true, + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-paging": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.5.0.tgz", + "integrity": "sha512-zqWdVIt+2Z+3wqxEOGzR5hXFZ8MGKK52x4vFLw8n58pR6ZfKRx3EXYTxTaYxYHc/PexPUTyimcTWFJbji9Z6Iw==", + "dev": true, + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.14.0.tgz", + "integrity": "sha512-Tp4M6NsjCmn9L5p7HsW98eSOS7A0ibl3e5ntZglozT0XuD/0y6i36iW829ZbBq0qihlGgfaeFpkLjZ418KDm1Q==", + "dev": true, + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.4.0", + "@azure/core-tracing": "^1.0.1", + "@azure/core-util": "^1.3.0", + "@azure/logger": "^1.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.0.0.tgz", + "integrity": "sha512-RP/mR/WJchR+g+nQFJGOec+nzeN/VvjlwbinccoqfhTsTHbb8X5+mLDp48kHT0ueyum0BNSwGm0kX0UZuIqTGg==", + "dev": true, + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-tracing": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", + "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", + "dev": true, + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@azure/core-util": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.7.0.tgz", + "integrity": "sha512-Zq2i3QO6k9DA8vnm29mYM4G8IE9u1mhF1GUabVEqPNX8Lj833gdxQ2NAFxt2BZsfAL+e9cT8SyVN7dFVJ/Hf0g==", + "dev": true, + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-util/node_modules/@azure/abort-controller": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.0.0.tgz", + "integrity": "sha512-RP/mR/WJchR+g+nQFJGOec+nzeN/VvjlwbinccoqfhTsTHbb8X5+mLDp48kHT0ueyum0BNSwGm0kX0UZuIqTGg==", + "dev": true, + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/identity": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-3.4.2.tgz", + "integrity": "sha512-0q5DL4uyR0EZ4RXQKD8MadGH6zTIcloUoS/RVbCpNpej4pwte0xpqYxk8K97Py2RiuUvI7F4GXpoT4046VfufA==", + "dev": true, + "dependencies": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-auth": "^1.5.0", + "@azure/core-client": "^1.4.0", + "@azure/core-rest-pipeline": "^1.1.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.6.1", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^3.5.0", + "@azure/msal-node": "^2.5.1", + "events": "^3.0.0", + "jws": "^4.0.0", + "open": "^8.0.0", + "stoppable": "^1.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@azure/keyvault-keys": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@azure/keyvault-keys/-/keyvault-keys-4.8.0.tgz", + "integrity": "sha512-jkuYxgkw0aaRfk40OQhFqDIupqblIOIlYESWB6DKCVDxQet1pyv86Tfk9M+5uFM0+mCs6+MUHU+Hxh3joiUn4Q==", + "dev": true, + "dependencies": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-auth": "^1.3.0", + "@azure/core-client": "^1.5.0", + "@azure/core-http-compat": "^2.0.1", + "@azure/core-lro": "^2.2.0", + "@azure/core-paging": "^1.1.1", + "@azure/core-rest-pipeline": "^1.8.1", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.0.0", + "@azure/logger": "^1.0.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/logger": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", + "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", + "dev": true, + "dependencies": { + "tslib": "^2.2.0" }, "engines": { "node": ">=14.0.0" } }, + "node_modules/@azure/msal-browser": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.10.0.tgz", + "integrity": "sha512-mnmi8dCXVNZI+AGRq0jKQ3YiodlIC4W9npr6FCB9WN6NQT+6rq+cIlxgUb//BjLyzKsnYo+i4LROGeMyU+6v1A==", + "dev": true, + "dependencies": { + "@azure/msal-common": "14.7.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "14.7.1", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.7.1.tgz", + "integrity": "sha512-v96btzjM7KrAu4NSEdOkhQSTGOuNUIIsUdB8wlyB9cdgl5KqEKnTonHUZ8+khvZ6Ap542FCErbnTyDWl8lZ2rA==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-node": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.6.4.tgz", + "integrity": "sha512-nNvEPx009/80UATCToF+29NZYocn01uKrB91xtFr7bSqkqO1PuQGXRyYwryWRztUrYZ1YsSbw9A+LmwOhpVvcg==", + "dev": true, + "dependencies": { + "@azure/msal-common": "14.7.1", + "jsonwebtoken": "^9.0.0", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@babel/code-frame": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -145,22 +502,26 @@ "node": ">=4" } }, - "node_modules/@babel/runtime": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.3.tgz", - "integrity": "sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, "node_modules/@esbuild/android-arm": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", - "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", "cpu": [ "arm" ], @@ -174,9 +535,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", - "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", "cpu": [ "arm64" ], @@ -190,9 +551,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", - "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", "cpu": [ "x64" ], @@ -206,9 +567,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", - "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", "cpu": [ "arm64" ], @@ -222,9 +583,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", - "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", "cpu": [ "x64" ], @@ -238,9 +599,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", - "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", "cpu": [ "arm64" ], @@ -254,9 +615,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", - "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", "cpu": [ "x64" ], @@ -270,9 +631,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", - "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", "cpu": [ "arm" ], @@ -286,9 +647,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", - "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", "cpu": [ "arm64" ], @@ -302,9 +663,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", - "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", "cpu": [ "ia32" ], @@ -318,9 +679,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", - "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", "cpu": [ "loong64" ], @@ -334,9 +695,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", - "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", "cpu": [ "mips64el" ], @@ -350,9 +711,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", - "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", "cpu": [ "ppc64" ], @@ -366,9 +727,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", - "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", "cpu": [ "riscv64" ], @@ -382,9 +743,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", - "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", "cpu": [ "s390x" ], @@ -398,9 +759,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", - "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", "cpu": [ "x64" ], @@ -414,9 +775,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", - "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", "cpu": [ "x64" ], @@ -430,9 +791,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", - "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", "cpu": [ "x64" ], @@ -446,9 +807,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", - "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", "cpu": [ "x64" ], @@ -462,9 +823,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", - "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", "cpu": [ "arm64" ], @@ -478,9 +839,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", - "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", "cpu": [ "ia32" ], @@ -494,9 +855,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", - "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", "cpu": [ "x64" ], @@ -510,17 +871,23 @@ } }, "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.25.16" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@js-joda/core": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@js-joda/core/-/core-5.6.1.tgz", + "integrity": "sha512-Xla/d7ZMMR6+zRd6lTio0wRZECfcfFJP7GGe9A9L4tDOlD5CX4YcZ4YZle9w58bBYzssojVapI84RraKWDQZRg==", + "dev": true + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -557,24 +924,24 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz", - "integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==", + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", + "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0" @@ -606,40 +973,52 @@ "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/@tsd/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@tsd/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-YQi2lvZSI+xidKeUjlbv6b6Zw7qB3aXHw5oGJLs5OOGAEqKIOvz5UIAkWyg0bJbkSUWPBEtaOHpVxU4EYBO1Jg==", - "dev": true + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@tsd/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-CQlfzol0ldaU+ftWuG52vH29uRoKboLinLy84wS8TQOu+m+tWoaUfk4svL4ij2V8M5284KymJBlHUusKj6k34w==", + "dev": true, + "engines": { + "node": ">=14.17" + } }, "node_modules/@types/better-sqlite3": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.4.tgz", - "integrity": "sha512-dzrRZCYPXIXfSR1/surNbJ/grU3scTaygS0OMzjlGf71i9sc2fGyHPXXiXmEvNIoE0cGwsanEFMVJxPXmco9Eg==", + "version": "7.6.9", + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.9.tgz", + "integrity": "sha512-FvktcujPDj9XKMJQWFcl2vVl7OdRIqsSRX9b0acWwTmwLK9CF2eqo/FRcmMLNpugKoX/avA6pb7TorDLmpgTnQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/chai": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", - "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", + "version": "4.3.12", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.12.tgz", + "integrity": "sha512-zNKDHG/1yxm8Il6uCCVsm+dRdEsJlFoDu73X17y09bId6UwoYww+vFBsAcRzl8knM1sab3Dp1VRikFQwDOtDDw==", "dev": true }, "node_modules/@types/chai-as-promised": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz", - "integrity": "sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ==", + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", + "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", "dev": true, "dependencies": { "@types/chai": "*" } }, "node_modules/@types/chai-subset": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", - "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.5.tgz", + "integrity": "sha512-c2mPnw+xHtXDoHmdtcCXGwyLMiauiAyxWMzhGpqHC4nqI/Y5G2XhTampslK2rb59kpcuHon03UH8W6iYUzw88A==", "dev": true, "dependencies": { "@types/chai": "*" @@ -656,45 +1035,48 @@ } }, "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", "dev": true }, "node_modules/@types/mocha": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", - "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", + "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", "dev": true }, "node_modules/@types/node": { - "version": "18.16.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.16.tgz", - "integrity": "sha512-NpaM49IGQQAUlBhHMF82QH80J08os4ZmyF9MkpCzWAGuOHqE4gTEbhzd7L3l5LmWuZ6E0OiC1FweQ4tsiW35+g==", - "dev": true + "version": "18.19.22", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.22.tgz", + "integrity": "sha512-p3pDIfuMg/aXBmhkyanPshdfJuX5c5+bQjYLIikPLXAUycEogij/c50n/C+8XOA5L93cU4ZRXtn+dNQGi0IZqQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, "node_modules/@types/pg": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.2.tgz", - "integrity": "sha512-MKFs9P6nJ+LAeHLU3V0cODEOgyThJ3OAnmOlsZsxux6sfQs3HRXR5bBn7xG5DjckEFhTAxsXi7k7cd0pCMxpJw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.2.tgz", + "integrity": "sha512-G2Mjygf2jFMU/9hCaTYxJrwdObdcnuQde1gndooZSOHsNSaCehAuwc7EIuSA34Do8Jx2yZ19KtvW8P0j4EuUXw==", "dev": true, "dependencies": { "@types/node": "*", @@ -703,43 +1085,92 @@ } }, "node_modules/@types/pg-cursor": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@types/pg-cursor/-/pg-cursor-2.7.0.tgz", - "integrity": "sha512-4Milg/OUqTO2VuPvvRwPxaQTaiVb+bXvSK+ZCwiHjwinbD4/lPqV9AREg8sJAT0cy5ruY38aaajBc2FbdPaKcA==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@types/pg-cursor/-/pg-cursor-2.7.2.tgz", + "integrity": "sha512-m3xT8bVFCvx98LuzbvXyuCdT/Hjdd/v8ml4jL4K1QF70Y8clOfCFdgoaEB1FWdcSwcpoFYZTJQaMD9/GQ27efQ==", "dev": true, "dependencies": { "@types/node": "*", "@types/pg": "*" } }, + "node_modules/@types/readable-stream": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.10.tgz", + "integrity": "sha512-AbUKBjcC8SHmImNi4yK2bbjogQlkFSg7shZCcicxPQapniOlajG8GCc39lvXzCWX4lLRRs7DM3VAeSlqmEVZUA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/@types/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, "node_modules/@types/sinon": { - "version": "10.0.15", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.15.tgz", - "integrity": "sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ==", + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", + "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", "dev": true, "dependencies": { "@types/sinonjs__fake-timers": "*" } }, "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", - "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", "dev": true }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "node_modules/@types/tedious": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", + "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", "dev": true, - "engines": { - "node": ">=6" + "dependencies": { + "@types/node": "*" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "dependencies": { "type-fest": "^0.21.3" @@ -760,12 +1191,6 @@ "node": ">=8" } }, - "node_modules/ansi-sequence-parser": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", - "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==", - "dev": true - }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -800,6 +1225,22 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -809,6 +1250,28 @@ "node": ">=8" } }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -827,6 +1290,21 @@ "node": "*" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -854,14 +1332,14 @@ ] }, "node_modules/better-sqlite3": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.4.0.tgz", - "integrity": "sha512-NmsNW1CQvqMszu/CFAJ3pLct6NEFlNfuGM6vw72KHkjOD1UDnL96XNN1BMQc1hiHo8vE2GbOWQYIpZ+YM5wrZw==", + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.4.3.tgz", + "integrity": "sha512-ud0bTmD9O3uWJGuXDltyj3R47Nz0OHX8iqPOT5PMspGqlu/qQFn+5S2eFBUCrySpavTjFXbi4EgrfVvPAHlImw==", "dev": true, "hasInstallScript": true, "dependencies": { "bindings": "^1.5.0", - "prebuild-install": "^7.1.0" + "prebuild-install": "^7.1.1" } }, "node_modules/binary-extensions": { @@ -944,6 +1422,12 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true + }, "node_modules/buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -953,6 +1437,25 @@ "node": ">=4" } }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -980,18 +1483,18 @@ } }, "node_modules/chai": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", - "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^4.1.2", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", "pathval": "^1.1.1", - "type-detect": "^4.0.5" + "type-detect": "^4.0.8" }, "engines": { "node": ">=4" @@ -1047,10 +1550,13 @@ } }, "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, "engines": { "node": "*" } @@ -1089,17 +1595,14 @@ "dev": true }, "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", + "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" } }, "node_modules/color-convert": { @@ -1120,55 +1623,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/concurrently": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.1.0.tgz", - "integrity": "sha512-0AB6eOAtaW/r/kX2lCdolaWtT191ICeuJjEJvI9hT3zbPFuZ/iZaJwMRKwbuwADome7OKxk73L7od+fsveZ7tA==", - "dev": true, - "dependencies": { - "chalk": "^4.1.2", - "date-fns": "^2.29.3", - "lodash": "^4.17.21", - "rxjs": "^7.8.0", - "shell-quote": "^1.8.0", - "spawn-command": "0.0.2-1", - "supports-color": "^8.1.1", - "tree-kill": "^1.2.2", - "yargs": "^17.7.1" - }, - "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" - }, - "engines": { - "node": "^14.13.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" - } - }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1262,6 +1716,49 @@ "node": ">=4.0.0" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -1272,9 +1769,9 @@ } }, "node_modules/detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", "dev": true, "engines": { "node": ">=8" @@ -1290,9 +1787,9 @@ } }, "node_modules/diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -1310,6 +1807,15 @@ "node": ">=8" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -1334,10 +1840,139 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-abstract": { + "version": "1.22.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", + "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.1", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.0", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-aggregate-error": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.12.tgz", + "integrity": "sha512-j0PupcmELoVbYS2NNrsn5zcLLEsryQwP02x8fRawh7c2eEaPHwJFAxltZsqV7HJjsF57+SMpYyVRWgbVLfOagg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.1.0", + "function-bind": "^1.1.2", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.1", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/esbuild": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", - "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", "dev": true, "hasInstallScript": true, "bin": { @@ -1347,34 +1982,35 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.17.19", - "@esbuild/android-arm64": "0.17.19", - "@esbuild/android-x64": "0.17.19", - "@esbuild/darwin-arm64": "0.17.19", - "@esbuild/darwin-x64": "0.17.19", - "@esbuild/freebsd-arm64": "0.17.19", - "@esbuild/freebsd-x64": "0.17.19", - "@esbuild/linux-arm": "0.17.19", - "@esbuild/linux-arm64": "0.17.19", - "@esbuild/linux-ia32": "0.17.19", - "@esbuild/linux-loong64": "0.17.19", - "@esbuild/linux-mips64el": "0.17.19", - "@esbuild/linux-ppc64": "0.17.19", - "@esbuild/linux-riscv64": "0.17.19", - "@esbuild/linux-s390x": "0.17.19", - "@esbuild/linux-x64": "0.17.19", - "@esbuild/netbsd-x64": "0.17.19", - "@esbuild/openbsd-x64": "0.17.19", - "@esbuild/sunos-x64": "0.17.19", - "@esbuild/win32-arm64": "0.17.19", - "@esbuild/win32-ia32": "0.17.19", - "@esbuild/win32-x64": "0.17.19" + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" @@ -1420,6 +2056,24 @@ "integrity": "sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A==", "dev": true }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -1430,9 +2084,9 @@ } }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -1446,9 +2100,9 @@ } }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -1497,6 +2151,15 @@ "flat": "cli.js" } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -1510,9 +2173,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -1524,10 +2187,40 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/generate-function": { "version": "2.3.1", @@ -1548,38 +2241,73 @@ } }, "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, "engines": { "node": "*" } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "dev": true - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "engines": { - "node": "*" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { @@ -1594,26 +2322,19 @@ "node": ">= 6" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "define-properties": "^1.1.3" }, "engines": { - "node": "*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/globby": { @@ -1636,6 +2357,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -1645,16 +2378,13 @@ "node": ">=6" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-flag": { @@ -1666,6 +2396,69 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -1699,6 +2492,33 @@ "node": ">=10" } }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -1732,9 +2552,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -1771,6 +2591,20 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/irregular-plurals": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", @@ -1780,12 +2614,40 @@ "node": ">=8" } }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1798,18 +2660,76 @@ "node": ">=8" } }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, "dependencies": { - "has": "^1.0.3" + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1840,6 +2760,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -1849,6 +2781,21 @@ "node": ">=0.12.0" } }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -1864,6 +2811,82 @@ "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", "dev": true }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -1876,36 +2899,66 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, "node_modules/jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/js-md4": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/js-md4/-/js-md4-0.3.2.tgz", + "integrity": "sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==", + "dev": true + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -1924,24 +2977,88 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbi": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-4.3.0.tgz", + "integrity": "sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dev": true, + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dev": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dev": true, + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } }, "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", "dev": true }, + "node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "dev": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "dev": true, + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -1984,6 +3101,48 @@ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -2007,12 +3166,12 @@ "dev": true }, "node_modules/loupe": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", - "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, "dependencies": { - "get-func-name": "^2.0.0" + "get-func-name": "^2.0.1" } }, "node_modules/lru-cache": { @@ -2024,12 +3183,6 @@ "node": ">=16.14" } }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true - }, "node_modules/map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", @@ -2042,18 +3195,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "dev": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/meow": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", @@ -2177,9 +3318,9 @@ "dev": true }, "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.3.0.tgz", + "integrity": "sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==", "dev": true, "dependencies": { "ansi-colors": "4.1.1", @@ -2189,13 +3330,12 @@ "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.2.0", + "glob": "8.1.0", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "5.0.1", "ms": "2.1.3", - "nanoid": "3.3.3", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", @@ -2210,39 +3350,6 @@ }, "engines": { "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" } }, "node_modules/ms": { @@ -2252,9 +3359,9 @@ "dev": true }, "node_modules/mysql2": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.3.3.tgz", - "integrity": "sha512-MxDQJztArk4JFX1PKVjDhIXRzAmVJfuqZrVU+my6NeYBAA/XZRaDw5q7vga8TNvgyy3Lv3rivBFBBuJFbsdjaw==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.2.tgz", + "integrity": "sha512-3Cwg/UuRkAv/wm6RhtPE5L7JlPB877vwSF6gfLAS68H+zhH+u5oa3AieqEd0D0/kC3W7qIhYbH419f7O9i/5nw==", "dev": true, "dependencies": { "denque": "^2.1.0", @@ -2291,50 +3398,35 @@ "node": ">=12" } }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, "node_modules/napi-build-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "dev": true }, - "node_modules/nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } + "node_modules/native-duplexpair": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/native-duplexpair/-/native-duplexpair-1.0.0.tgz", + "integrity": "sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA==", + "dev": true }, - "node_modules/nise/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "node_modules/nise": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", + "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", "dev": true, "dependencies": { - "type-detect": "4.0.8" + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/text-encoding": "^0.7.2", + "just-extend": "^6.2.0", + "path-to-regexp": "^6.2.1" } }, "node_modules/node-abi": { - "version": "3.43.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.43.0.tgz", - "integrity": "sha512-QB0MMv+tn9Ur2DtJrc8y09n0n6sw88CyDniWSX2cHW10goQXYPK9ZpFJOktDS4ron501edPX6h9i7Pg+RnH5nQ==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.56.0.tgz", + "integrity": "sha512-fZjdhDOeRcaS+rcpve7XuwHBmktS1nS1gzgghwKUQQ8nTy2FdSDr6ZT8k6YhvlJeHmmQMYiT/IH9hfco5zeW2Q==", "dev": true, "dependencies": { "semver": "^7.3.5" @@ -2343,6 +3435,12 @@ "node": ">=10" } }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true + }, "node_modules/normalize-package-data": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", @@ -2367,6 +3465,42 @@ "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -2382,6 +3516,23 @@ "wrappy": "1" } }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -2454,29 +3605,17 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "dependencies": { - "isarray": "0.0.1" - } + "node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true }, "node_modules/path-type": { "version": "4.0.0", @@ -2497,15 +3636,15 @@ } }, "node_modules/pg": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.0.tgz", - "integrity": "sha512-meLUVPn2TWgJyLmy7el3fQQVwft4gU5NGyvV0XbD41iU9Jbg8lCH4zexhIkihDzVHJStlt6r088G6/fWeNjhXA==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", "dev": true, "dependencies": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "^2.6.0", - "pg-pool": "^3.6.0", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", "pg-protocol": "^1.6.0", "pg-types": "^2.1.0", "pgpass": "1.x" @@ -2514,7 +3653,7 @@ "node": ">= 8.0.0" }, "optionalDependencies": { - "pg-cloudflare": "^1.1.0" + "pg-cloudflare": "^1.1.1" }, "peerDependencies": { "pg-native": ">=3.0.1" @@ -2526,22 +3665,22 @@ } }, "node_modules/pg-cloudflare": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.0.tgz", - "integrity": "sha512-tGM8/s6frwuAIyRcJ6nWcIvd3+3NmUKIs6OjviIm1HPPFEt5MzQDOTBQyhPWg/m0kCl95M6gA1JaIXtS8KovOA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", "dev": true, "optional": true }, "node_modules/pg-connection-string": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.0.tgz", - "integrity": "sha512-x14ibktcwlHKoHxx9X3uTVW9zIGR41ZB6QNhHb21OPNdCCO3NaRnpJuwKIQSR4u+Yqjx4HCvy7Hh7VSy1U4dGg==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==", "dev": true }, "node_modules/pg-cursor": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/pg-cursor/-/pg-cursor-2.10.0.tgz", - "integrity": "sha512-azXIjeIGBwlv/icYyuki5xJYfVSXeirGn4+mvAmYTB8SY0gS1xhluc2CENnq1JrcVSA81lWZgtqc1GAAhH/UuQ==", + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/pg-cursor/-/pg-cursor-2.10.3.tgz", + "integrity": "sha512-rDyBVoqPVnx/PTmnwQAYgusSeAKlTL++gmpf5klVK+mYMFEqsOc6VHHZnPKc/4lOvr4r6fiMuoxSFuBF1dx4FQ==", "dev": true, "peerDependencies": { "pg": "^8" @@ -2566,9 +3705,9 @@ } }, "node_modules/pg-pool": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.0.tgz", - "integrity": "sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", "dev": true, "peerDependencies": { "pg": ">=8.0" @@ -2581,16 +3720,16 @@ "dev": true }, "node_modules/pg-types": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", - "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.2.tgz", + "integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==", "dev": true, "dependencies": { "pg-int8": "1.0.1", "pg-numeric": "1.0.2", "postgres-array": "~3.0.1", "postgres-bytea": "~3.0.0", - "postgres-date": "~2.0.1", + "postgres-date": "~2.1.0", "postgres-interval": "^3.0.0", "postgres-range": "^1.1.1" }, @@ -2675,31 +3814,47 @@ } }, "node_modules/playwright": { - "version": "1.34.3", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.34.3.tgz", - "integrity": "sha512-UOOVE4ZbGfGkP1KVqWTdXOmm8Pw2pBhfbmlqKMkpiRCQjL5W+J+xRQXpgutFr0iM4pWl8g0GyyASMsqjQfFohw==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz", + "integrity": "sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==", "dev": true, - "hasInstallScript": true, "dependencies": { - "playwright-core": "1.34.3" + "playwright-core": "1.42.1" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=14" + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.34.3", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.34.3.tgz", - "integrity": "sha512-2pWd6G7OHKemc5x1r1rp8aQcpvDh7goMBZlJv6Co5vCNLVcQJdhxRL09SGaY6HcyHH9aT4tiynZabMofVasBYw==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.1.tgz", + "integrity": "sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==", "dev": true, "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=14" + "node": ">=16" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/plur": { @@ -2717,6 +3872,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postgres-array": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", @@ -2739,9 +3903,9 @@ } }, "node_modules/postgres-date": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", - "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz", + "integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==", "dev": true, "engines": { "node": ">=12" @@ -2757,15 +3921,15 @@ } }, "node_modules/postgres-range": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", - "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.4.tgz", + "integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==", "dev": true }, "node_modules/prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", "dev": true, "dependencies": { "detect-libc": "^2.0.0", @@ -2789,27 +3953,27 @@ } }, "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -2829,6 +3993,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -3019,9 +4192,9 @@ } }, "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -3075,11 +4248,23 @@ "node": ">=8" } }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/require-directory": { "version": "2.1.1", @@ -3091,12 +4276,12 @@ } }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -3140,13 +4325,22 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "node_modules/safe-array-concat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", "dev": true, "dependencies": { - "tslib": "^2.1.0" + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/safe-buffer": { @@ -3169,6 +4363,23 @@ } ] }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -3176,9 +4387,9 @@ "dev": true }, "node_modules/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -3217,25 +4428,54 @@ "randombytes": "^2.1.0" } }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "node_modules/set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/shiki": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.2.tgz", - "integrity": "sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==", + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "ansi-sequence-parser": "^1.1.0", - "jsonc-parser": "^3.2.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^8.0.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/simple-concat": { @@ -3284,16 +4524,16 @@ } }, "node_modules/sinon": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.1.0.tgz", - "integrity": "sha512-cS5FgpDdE9/zx7no8bxROHymSlPLZzq0ChbbLk1DrxBfc+eTeBK3y8nIL+nu/0QeYydhhbLIr7ecHJpywjQaoQ==", + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-17.0.1.tgz", + "integrity": "sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^10.2.0", + "@sinonjs/fake-timers": "^11.2.2", "@sinonjs/samsam": "^8.0.0", "diff": "^5.1.0", - "nise": "^5.1.4", + "nise": "^5.1.5", "supports-color": "^7.2.0" }, "funding": { @@ -3302,9 +4542,9 @@ } }, "node_modules/sinon/node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, "engines": { "node": ">=0.3.1" @@ -3331,12 +4571,6 @@ "node": ">=8" } }, - "node_modules/spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", - "dev": true - }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -3348,9 +4582,9 @@ } }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true }, "node_modules/spdx-expression-parse": { @@ -3364,9 +4598,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", "dev": true }, "node_modules/split2": { @@ -3378,6 +4612,12 @@ "node": ">= 10.x" } }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true + }, "node_modules/sqlstring": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", @@ -3387,6 +4627,16 @@ "node": ">= 0.6" } }, + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "dev": true, + "engines": { + "node": ">=4", + "npm": ">=6" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -3410,6 +4660,51 @@ "node": ">=8" } }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -3526,6 +4821,89 @@ "node": ">=6" } }, + "node_modules/tarn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz", + "integrity": "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/tedious": { + "version": "16.7.1", + "resolved": "https://registry.npmjs.org/tedious/-/tedious-16.7.1.tgz", + "integrity": "sha512-NmedZS0NJiTv3CoYnf1FtjxIDUgVYzEmavrc8q2WHRb+lP4deI9BpQfmNnBZZaWusDbP5FVFZCcvzb3xOlNVlQ==", + "dev": true, + "dependencies": { + "@azure/identity": "^3.4.1", + "@azure/keyvault-keys": "^4.4.0", + "@js-joda/core": "^5.5.3", + "bl": "^6.0.3", + "es-aggregate-error": "^1.0.9", + "iconv-lite": "^0.6.3", + "js-md4": "^0.3.2", + "jsbi": "^4.3.0", + "native-duplexpair": "^1.0.0", + "node-abort-controller": "^3.1.1", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tedious/node_modules/bl": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/bl/-/bl-6.0.12.tgz", + "integrity": "sha512-EnEYHilP93oaOa2MnmNEjAcovPS3JlQZOyzGXi3EyEpPhm9qWvdDp7BmAVEVusGzp8LlwQK56Av+OkDoRjzE0w==", + "dev": true, + "dependencies": { + "@types/readable-stream": "^4.0.0", + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^4.2.0" + } + }, + "node_modules/tedious/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/tedious/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3538,15 +4916,6 @@ "node": ">=8.0" } }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", @@ -3557,12 +4926,12 @@ } }, "node_modules/tsd": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/tsd/-/tsd-0.28.1.tgz", - "integrity": "sha512-FeYrfJ05QgEMW/qOukNCr4fAJHww4SaKnivAXRv4g5kj4FeLpNV7zH4dorzB9zAfVX4wmA7zWu/wQf7kkcvfbw==", + "version": "0.30.7", + "resolved": "https://registry.npmjs.org/tsd/-/tsd-0.30.7.tgz", + "integrity": "sha512-oTiJ28D6B/KXoU3ww/Eji+xqHJojiuPVMwA12g4KYX1O72N93Nb6P3P3h2OAhhf92Xl8NIhb/xFmBZd5zw/xUw==", "dev": true, "dependencies": { - "@tsd/typescript": "~5.0.2", + "@tsd/typescript": "~5.3.3", "eslint-formatter-pretty": "^4.1.0", "globby": "^11.0.1", "jest-diff": "^29.0.3", @@ -3578,9 +4947,9 @@ } }, "node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, "node_modules/tunnel-agent": { @@ -3616,46 +4985,83 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typedoc": { - "version": "0.24.8", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", - "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, "dependencies": { - "lunr": "^2.3.9", - "marked": "^4.3.0", - "minimatch": "^9.0.0", - "shiki": "^0.14.1" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, - "bin": { - "typedoc": "bin/typedoc" + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { - "node": ">= 14.14" + "node": ">= 0.4" }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", + "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/typescript": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", - "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -3665,12 +5071,42 @@ "node": ">=14.17" } }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -3681,17 +5117,40 @@ "spdx-expression-parse": "^3.0.0" } }, - "node_modules/vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "dev": true + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/vscode-textmate": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", - "dev": true + "node_modules/which-typed-array": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/workerpool": { "version": "6.2.1", @@ -3747,21 +5206,21 @@ "dev": true }, "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { - "cliui": "^8.0.1", + "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.3", + "string-width": "^4.2.0", "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "yargs-parser": "^20.2.2" }, "engines": { - "node": ">=12" + "node": ">=10" } }, "node_modules/yargs-parser": { @@ -3821,15 +5280,6 @@ "node": ">=8" } }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 053e761d5..fc42c2391 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "kysely", - "version": "0.25.0", + "version": "0.27.3", "description": "Type safe SQL query builder", "repository": { "type": "git", - "url": "git://github.com/koskimas/kysely.git" + "url": "git://github.com/kysely-org/kysely.git" }, "engines": { "node": ">=14.0.0" @@ -26,29 +26,36 @@ "import": "./dist/esm/helpers/mysql.js", "require": "./dist/cjs/helpers/mysql.js", "default": "./dist/cjs/helpers/mysql.js" + }, + "./helpers/mssql": { + "import": "./dist/esm/helpers/mssql.js", + "require": "./dist/cjs/helpers/mssql.js", + "default": "./dist/cjs/helpers/mssql.js" + }, + "./helpers/sqlite": { + "import": "./dist/esm/helpers/sqlite.js", + "require": "./dist/cjs/helpers/sqlite.js", + "default": "./dist/cjs/helpers/sqlite.js" } }, "scripts": { "clean": "rm -rf dist & rm -rf test/node/dist & rm -rf test/browser/bundle.js & rm -rf helpers", - "test": "npm run build && npm run test:node:build && concurrently -n node,typings,esmimports \"npm run test:node\" \"npm run test:typings\" \"npm run test:esmimports\"", + "test": "npm run build && npm run test:node:build && npm run test:node:run && npm run test:typings && npm run test:esmimports", "test:node:build": "tsc -p test/node", - "test:node": "concurrently -n postgres,mysql,sqlite \"npm run test:node:postgres\" \"npm run test:node:mysql\" \"npm run test:node:sqlite\"", - "test:node:postgres": "DIALECT=postgres npm run test:node:run", - "test:node:mysql": "DIALECT=mysql npm run test:node:run", - "test:node:sqlite": "DIALECT=sqlite npm run test:node:run", + "test:node": "npm run build && npm run test:node:build && npm run test:node:run", "test:node:run": "mocha --timeout 15000 test/node/dist/**/*.test.js", "test:browser:build": "rm -rf test/browser/bundle.js && esbuild test/browser/main.ts --bundle --outfile=test/browser/bundle.js", "test:browser": "npm run build && npm run test:browser:build && node test/browser/test.js", - "test:deno": "npm run build && deno run test/deno/local.test.ts && deno run test/deno/cdn.test.ts", + "test:bun": "npm run build && cd test/bun && bun install && bun run test", + "test:cloudflare-workers": "npm run build && cd test/cloudflare-workers && npm ci && npm test", + "test:deno": "npm run build && deno run --allow-env --allow-read --allow-net test/deno/local.test.ts && deno run --allow-env --allow-read --allow-net test/deno/cdn.test.ts", "test:typings": "tsd test/typings", "test:esmimports": "node scripts/check-esm-imports.js", "test:esbuild": "esbuild --bundle --platform=node --external:pg-native dist/esm/index.js --outfile=/dev/null", "prettier": "prettier --write 'src/**/*.ts' 'test/**/*.ts'", - "build": "npm run clean && concurrently -n esm,cjs \"npm run build:esm\" \"npm run build:cjs\" && concurrently -n modulefix,docfix \"npm run script:module-fixup\" \"npm run script:copy-interface-doc\"", + "build": "npm run clean && (npm run build:esm & npm run build:cjs) && npm run script:module-fixup && npm run script:copy-interface-doc", "build:esm": "tsc -p tsconfig.json && npm run script:add-deno-type-references", "build:cjs": "tsc -p tsconfig-cjs.json", - "docs:build": "typedoc --excludePrivate --excludeInternal --customCss ./docs-theme.css src/index.ts && npm run docs:postprocess", - "docs:postprocess": "node scripts/post-process-docs.js", "script:module-fixup": "node scripts/module-fixup.js", "script:copy-interface-doc": "node scripts/copy-interface-documentation.js", "script:add-deno-type-references": "node scripts/add-deno-type-references.js", @@ -58,33 +65,36 @@ "author": "Sami Koskimäki ", "license": "MIT", "contributors": [ + "Sami Koskimäki ", "Igal Klebanov " ], "devDependencies": { - "@types/better-sqlite3": "^7.6.4", - "@types/chai": "^4.3.5", - "@types/chai-as-promised": "^7.1.5", - "@types/chai-subset": "^1.3.3", - "@types/mocha": "^10.0.1", + "@types/better-sqlite3": "^7.6.8", + "@types/chai": "^4.3.11", + "@types/chai-as-promised": "^7.1.8", + "@types/chai-subset": "^1.3.5", + "@types/mocha": "^10.0.6", "@types/node": "^18.15.11", - "@types/pg": "^8.10.2", - "@types/pg-cursor": "^2.7.0", - "@types/sinon": "^10.0.15", - "better-sqlite3": "^8.4.0", - "chai": "^4.3.7", + "@types/pg": "^8.10.9", + "@types/pg-cursor": "^2.7.2", + "@types/sinon": "^17.0.2", + "@types/tedious": "^4.0.9", + "better-sqlite3": "^9.2.2", + "chai": "^4.4.0", "chai-as-promised": "^7.1.1", "chai-subset": "^1.6.0", - "concurrently": "^8.1.0", - "esbuild": "^0.17.19", + "esbuild": "^0.19.11", + "lodash": "^4.17.21", "mocha": "^10.2.0", - "mysql2": "^3.3.3", - "pg": "^8.11.0", - "pg-cursor": "^2.10.0", - "playwright": "^1.34.3", - "prettier": "^2.8.8", - "sinon": "^15.1.0", - "tsd": "^0.28.1", - "typedoc": "^0.24.8", - "typescript": "5.1.3" + "mysql2": "^3.6.5", + "pg": "^8.11.3", + "pg-cursor": "^2.10.3", + "playwright": "^1.40.1", + "prettier": "^3.1.1", + "sinon": "^17.0.1", + "tarn": "^3.0.2", + "tedious": "^16.4.0", + "tsd": "^0.30.3", + "typescript": "^5.4.2" } } diff --git a/scripts/generate-site-examples.js b/scripts/generate-site-examples.js index e450443e3..b20244087 100644 --- a/scripts/generate-site-examples.js +++ b/scripts/generate-site-examples.js @@ -25,55 +25,55 @@ const CODE_LINE_REGEX = /\*(.*)/ const moreExamplesByCategory = { select: { 'select method': - 'https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select', + 'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select', 'selectAll method': - 'https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#selectAll', + 'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll', 'selectFrom method': - 'https://kysely-org.github.io/kysely/classes/Kysely.html#selectFrom', + 'https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom', }, where: { 'where method': - 'https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#where', + 'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where', 'whereRef method': - 'https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#whereRef', + 'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef', }, join: { 'innerJoin method': - 'https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#innerJoin', + 'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#innerJoin', 'leftJoin method': - 'https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#leftJoin', + 'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#leftJoin', 'rightJoin method': - 'https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#rightJoin', + 'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#rightJoin', 'fullJoin method': - 'https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#fullJoin', + 'https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#fullJoin', }, insert: { 'values method': - 'https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#values', + 'https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#values', 'onConflict method': - 'https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#onConflict', + 'https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#onConflict', 'returning method': - 'https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#returning', + 'https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#returning', 'insertInto method': - 'https://kysely-org.github.io/kysely/classes/Kysely.html#insertInto', + 'https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#insertInto', }, update: { 'set method': - 'https://kysely-org.github.io/kysely/classes/UpdateQueryBuilder.html#set', + 'https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#set', 'returning method': - 'https://kysely-org.github.io/kysely/classes/UpdateQueryBuilder.html#returning', + 'https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#returning', 'updateTable method': - 'https://kysely-org.github.io/kysely/classes/Kysely.html#updateTable', + 'https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#updateTable', }, delete: { 'deleteFrom method': - 'https://kysely-org.github.io/kysely/classes/Kysely.html#deleteFrom', + 'https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#deleteFrom', 'returning method': - 'https://kysely-org.github.io/kysely/classes/DeleteQueryBuilder.html#returning', + 'https://kysely-org.github.io/kysely-apidoc/classes/DeleteQueryBuilder.html#returning', }, transactions: { 'transaction method': - 'https://kysely-org.github.io/kysely/classes/Kysely.html#transaction', + 'https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#transaction', }, } @@ -209,7 +209,7 @@ function buildMoreExamplesMarkdown(category) { const lines = [ ':::info More examples', - 'The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/)', + 'The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/)', 'but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always', 'just one hover away!', '', diff --git a/scripts/manage-site-examples.js b/scripts/manage-site-examples.js deleted file mode 100644 index 2695fb50e..000000000 --- a/scripts/manage-site-examples.js +++ /dev/null @@ -1,146 +0,0 @@ -/** - * Manage website's example files: - * - * node manage-site-examples.js add select 5 "The name of the example" - * node manage-site-examples.js remove select 5 - * - */ -const fs = require('fs') -const path = require('path') -const _ = require('lodash') - -const cmd = process.argv[2] -if (cmd !== 'add' && cmd !== 'remove') { - console.error('first argument must be the command (add | remove)') - process.exit(1) -} - -const section = process.argv[3] -if (!section) { - console.error('second argument must be the example section') - process.exit(1) -} - -const index = parseInt(process.argv[4]) -if (!index) { - console.error('third argument must be the example index in the section') - process.exit(1) -} - -const name = process.argv[5] -if (cmd === 'add' && !name) { - console.error('fourth argument must be the name of the example') - process.exit(1) -} - -const examplesDir = path.join( - __dirname, - '..', - 'site', - 'docs', - 'examples', - section.toUpperCase() -) - -const examples = fs - .readdirSync(examplesDir) - .sort() - .map((e) => e.split('-')) - .filter((e) => !Number.isNaN(parseInt(e[0]))) - .map((e) => ({ - index: parseInt(e[0]), - nameParts: e.slice(1), - fileName: e.join('-'), - })) - -if (cmd === 'add') { - makeRoom() - add() -} else if (cmd === 'remove') { - remove() - fixupIndices() -} - -function add() { - const exampleCodeImport = `example${_.upperFirst(_.camelCase(name))}` - - const code = trimLines(` - --- - title: '${name}' - --- - - # ${name} - - TODO: Description - - import { - Playground, - exampleSetup, - ${exampleCodeImport} - } from '../../../src/components/Playground' - - - `) - - fs.writeFileSync( - path.join(examplesDir, `${zeroPad(index)}-${_.kebabCase(name)}.mdx`), - code - ) -} - -function remove() { - const ei = examples.findIndex((e) => e.index === index) - - if (ei !== -1) { - fs.unlinkSync(path.join(examplesDir, examples[ei].fileName)) - examples.splice(ei, 1) - } -} - -function makeRoom() { - if (examples.every((e) => e.index !== index)) { - // No need to make room. - return - } - - for (const e of examples) { - if (e.index >= index) { - fs.renameSync( - path.join(examplesDir, e.fileName), - path.join( - examplesDir, - `${zeroPad(e.index + 1)}-${e.nameParts.join('-')}` - ) - ) - } - } -} - -function fixupIndices() { - const fixedExamples = examples.map((e, i) => ({ - ...e, - newIndex: i + 1, - })) - - for (const e of fixedExamples) { - fs.renameSync( - path.join(examplesDir, e.fileName), - path.join(examplesDir, `${zeroPad(e.newIndex)}-${e.nameParts.join('-')}`) - ) - } -} - -function zeroPad(i) { - return i.toString().padStart(4, '0') -} - -function trimLines(str) { - const lines = str.split('\n') - - while (lines[0].trim().length === 0) { - lines.splice(0, 1) - } - - const indent = lines[0].length - lines[0].trimStart().length - return lines.map((l) => l.substr(indent)).join('\n') -} diff --git a/scripts/module-fixup.js b/scripts/module-fixup.js index b0e1d5236..9267f856c 100755 --- a/scripts/module-fixup.js +++ b/scripts/module-fixup.js @@ -34,9 +34,9 @@ for (const ex of Object.keys(package.exports)) { const [, ...targetFolders] = package.exports[ex].require.split('/') const targetFileName = targetFolders.pop() - const target = path.relative( - path.join(ROOT_PATH, ...folders), - path.join(ROOT_PATH, ...targetFolders, targetFileName) + const target = path.posix.relative( + path.posix.join(ROOT_PATH, ...folders), + path.posix.join(ROOT_PATH, ...targetFolders, targetFileName) ) fs.mkdirSync(path.join(ROOT_PATH, ...folders), { diff --git a/scripts/post-process-docs.js b/scripts/post-process-docs.js deleted file mode 100644 index 397d15a14..000000000 --- a/scripts/post-process-docs.js +++ /dev/null @@ -1,31 +0,0 @@ -const fs = require('fs') -const path = require('path') - -const DOCS_PATH = path.join(__dirname, '..', 'docs') -const DOCS_ASSET_PATH = path.join(DOCS_PATH, 'assets') - -const ASSET_PATH = path.join(__dirname, '..', 'assets') - -// Files to go through and replace ASSET_URL_BASE with FIXED_ASSET_URL_BASE. -const ASSET_FIX_FILES = [path.join(DOCS_PATH, 'index.html')] -const ASSET_URL_BASE = - /https:\/\/github.com\/koskimas\/kysely\/blob\/master\/assets/g -const FIXED_ASSET_URL_BASE = 'assets' - -// Copy all assets to doc assets. -for (const assetName of fs.readdirSync(ASSET_PATH)) { - fs.copyFileSync( - path.join(ASSET_PATH, assetName), - path.join(DOCS_ASSET_PATH, assetName) - ) -} - -// Fix asset urls. -for (const filePath of ASSET_FIX_FILES) { - const file = fs - .readFileSync(filePath) - .toString() - .replace(ASSET_URL_BASE, FIXED_ASSET_URL_BASE) - - fs.writeFileSync(filePath, file) -} diff --git a/site/docs/dialects.md b/site/docs/dialects.md index b0964b4a7..f985e22fe 100644 --- a/site/docs/dialects.md +++ b/site/docs/dialects.md @@ -1,26 +1,37 @@ # Dialects -A dialect is the glue between Kysely and the underlying database engine. Check the [API docs](https://kysely-org.github.io/kysely/interfaces/Dialect.html) to learn how to build your own. +A dialect is the glue between Kysely and the underlying database engine. Check the [API docs](https://kysely-org.github.io/kysely-apidoc/interfaces/Dialect.html) to learn how to build your own. -## Built-in dialects +## Core dialects | Dialect | Link | | --- | --- | -| MySQL | https://kysely-org.github.io/kysely/classes/MysqlDialect.html | -| PostgreSQL | https://kysely-org.github.io/kysely/classes/PostgresDialect.html | -| SQLite | https://kysely-org.github.io/kysely/classes/SqliteDialect.html | +| PostgreSQL | https://kysely-org.github.io/kysely-apidoc/classes/PostgresDialect.html | +| MySQL | https://kysely-org.github.io/kysely-apidoc/classes/MysqlDialect.html | +| Microsoft SQL Server (MSSQL) | https://kysely-org.github.io/kysely-apidoc/classes/MssqlDialect.html | +| SQLite | https://kysely-org.github.io/kysely-apidoc/classes/SqliteDialect.html | -## 3rd party dialects +## Organization dialects | Dialect | Link | | --- | --- | -| PlanetScale Serverless Driver | https://github.com/depot/kysely-planetscale | -| Cloudflare D1 | https://github.com/aidenwallis/kysely-d1 | -| AWS RDS Data API | https://github.com/serverless-stack/kysely-data-api | -| SurrealDB | https://github.com/igalklebanov/kysely-surrealdb | -| Neon | https://github.com/seveibar/kysely-neon | -| AWS S3 Select | https://github.com/igalklebanov/kysely-s3-select | -| libSQL/sqld | https://github.com/libsql/kysely-libsql | -| SingleStore Data API | https://github.com/igalklebanov/kysely-singlestore | -| Postgres.js | https://github.com/igalklebanov/kysely-postgres-js | -| Fetch driver | https://github.com/andersgee/kysely-fetch-driver | +| Postgres.js | https://github.com/kysely-org/kysely-postgres-js | +| SingleStore Data API | https://github.com/kysely-org/kysely-singlestore | + +## Community dialects + +| Dialect | Link | +|-------------------------------|-----------------------------------------------------------------------------| +| PlanetScale Serverless Driver | https://github.com/depot/kysely-planetscale | +| Cloudflare D1 | https://github.com/aidenwallis/kysely-d1 | +| AWS RDS Data API | https://github.com/serverless-stack/kysely-data-api | +| SurrealDB | https://github.com/igalklebanov/kysely-surrealdb | +| Neon | https://github.com/seveibar/kysely-neon | +| Xata | https://github.com/xataio/client-ts/tree/main/packages/plugin-client-kysely | +| AWS S3 Select | https://github.com/igalklebanov/kysely-s3-select | +| libSQL/sqld | https://github.com/libsql/kysely-libsql | +| Fetch driver | https://github.com/andersgee/kysely-fetch-driver | +| SQLite WASM | https://github.com/DallasHoff/sqlocal | +| Deno SQLite | https://gitlab.com/soapbox-pub/kysely-deno-sqlite | +| TiDB Cloud Serverless Driver | https://github.com/tidbcloud/kysely | +| Capacitor SQLite Kysely | https://github.com/DawidWetzler/capacitor-sqlite-kysely | \ No newline at end of file diff --git a/site/docs/examples/DELETE/0010-single-row.mdx b/site/docs/examples/DELETE/0010-single-row.mdx index 3f8646841..922cf9678 100644 --- a/site/docs/examples/DELETE/0010-single-row.mdx +++ b/site/docs/examples/DELETE/0010-single-row.mdx @@ -20,11 +20,11 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [deleteFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#deleteFrom) - - [returning method](https://kysely-org.github.io/kysely/classes/DeleteQueryBuilder.html#returning) + - [deleteFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#deleteFrom) + - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/DeleteQueryBuilder.html#returning) ::: \ No newline at end of file diff --git a/site/docs/examples/INSERT/0010-single-row.js b/site/docs/examples/INSERT/0010-single-row.js index 4f8ec5485..843bff7a1 100644 --- a/site/docs/examples/INSERT/0010-single-row.js +++ b/site/docs/examples/INSERT/0010-single-row.js @@ -7,4 +7,9 @@ export const singleRow = `const result = await db }) .executeTakeFirst() +// \`insertId\` is only available on dialects that +// automatically return the id of the inserted row +// such as MySQL and SQLite. On PostgreSQL, for example, +// you need to add a \`returning\` clause to the query to +// get anything out. See the "returning data" example. console.log(result.insertId)` \ No newline at end of file diff --git a/site/docs/examples/INSERT/0010-single-row.mdx b/site/docs/examples/INSERT/0010-single-row.mdx index 0a5f7f966..b5085b83a 100644 --- a/site/docs/examples/INSERT/0010-single-row.mdx +++ b/site/docs/examples/INSERT/0010-single-row.mdx @@ -20,13 +20,13 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [values method](https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#values) - - [onConflict method](https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#onConflict) - - [returning method](https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#returning) - - [insertInto method](https://kysely-org.github.io/kysely/classes/Kysely.html#insertInto) + - [values method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#values) + - [onConflict method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#onConflict) + - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#returning) + - [insertInto method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#insertInto) ::: \ No newline at end of file diff --git a/site/docs/examples/INSERT/0020-multiple-rows.mdx b/site/docs/examples/INSERT/0020-multiple-rows.mdx index f02f79872..c8a638778 100644 --- a/site/docs/examples/INSERT/0020-multiple-rows.mdx +++ b/site/docs/examples/INSERT/0020-multiple-rows.mdx @@ -23,13 +23,13 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [values method](https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#values) - - [onConflict method](https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#onConflict) - - [returning method](https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#returning) - - [insertInto method](https://kysely-org.github.io/kysely/classes/Kysely.html#insertInto) + - [values method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#values) + - [onConflict method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#onConflict) + - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#returning) + - [insertInto method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#insertInto) ::: \ No newline at end of file diff --git a/site/docs/examples/INSERT/0030-returning-data.mdx b/site/docs/examples/INSERT/0030-returning-data.mdx index c560da912..5ad8f6cee 100644 --- a/site/docs/examples/INSERT/0030-returning-data.mdx +++ b/site/docs/examples/INSERT/0030-returning-data.mdx @@ -23,13 +23,13 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [values method](https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#values) - - [onConflict method](https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#onConflict) - - [returning method](https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#returning) - - [insertInto method](https://kysely-org.github.io/kysely/classes/Kysely.html#insertInto) + - [values method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#values) + - [onConflict method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#onConflict) + - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#returning) + - [insertInto method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#insertInto) ::: \ No newline at end of file diff --git a/site/docs/examples/INSERT/0040-complex-values.js b/site/docs/examples/INSERT/0040-complex-values.js index d0fee0dab..29292c59b 100644 --- a/site/docs/examples/INSERT/0040-complex-values.js +++ b/site/docs/examples/INSERT/0040-complex-values.js @@ -1,13 +1,15 @@ export const complexValues = `import { sql } from 'kysely' +const ani = "Ani" +const ston = "ston" + const result = await db .insertInto('person') .values(({ ref, selectFrom, fn }) => ({ first_name: 'Jennifer', - last_name: sql\`\${'Ani'} || \${'ston'}\`, + last_name: sql\`>concat(\${ani}, \${ston})\`, middle_name: ref('first_name'), age: selectFrom('person') - .select(fn.avg('age') - .as('avg_age')), + .select(fn.avg('age').as('avg_age')), })) .executeTakeFirst()` \ No newline at end of file diff --git a/site/docs/examples/INSERT/0040-complex-values.mdx b/site/docs/examples/INSERT/0040-complex-values.mdx index c640dbaab..9fd9ccd9f 100644 --- a/site/docs/examples/INSERT/0040-complex-values.mdx +++ b/site/docs/examples/INSERT/0040-complex-values.mdx @@ -22,13 +22,13 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [values method](https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#values) - - [onConflict method](https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#onConflict) - - [returning method](https://kysely-org.github.io/kysely/classes/InsertQueryBuilder.html#returning) - - [insertInto method](https://kysely-org.github.io/kysely/classes/Kysely.html#insertInto) + - [values method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#values) + - [onConflict method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#onConflict) + - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#returning) + - [insertInto method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#insertInto) ::: \ No newline at end of file diff --git a/site/docs/examples/INSERT/0050-insert-subquery.js b/site/docs/examples/INSERT/0050-insert-subquery.js new file mode 100644 index 000000000..5e5681e3d --- /dev/null +++ b/site/docs/examples/INSERT/0050-insert-subquery.js @@ -0,0 +1,11 @@ +export const insertSubquery = `const result = await db.insertInto('person') + .columns(['first_name', 'last_name', 'age']) + .expression((eb) => eb + .selectFrom('pet') + .select((eb) => [ + 'pet.name', + eb.val('Petson').as('last_name'), + eb.lit(7).as('age'), + ]) + ) + .execute()` \ No newline at end of file diff --git a/site/docs/examples/INSERT/0050-insert-subquery.mdx b/site/docs/examples/INSERT/0050-insert-subquery.mdx new file mode 100644 index 000000000..c8db4687f --- /dev/null +++ b/site/docs/examples/INSERT/0050-insert-subquery.mdx @@ -0,0 +1,34 @@ +--- +title: 'Insert subquery' +--- + +# Insert subquery + +You can create an `INSERT INTO SELECT FROM` query using the `expression` method. +This API doesn't follow our WYSIWYG principles and might be a bit difficult to +remember. The reasons for this design stem from implementation difficulties. + +import { + Playground, + exampleSetup, +} from '../../../src/components/Playground' + +import { + insertSubquery +} from './0050-insert-subquery' + +
+ +
+ +:::info More examples +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) +but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always +just one hover away! + +For example, check out these sections: + - [values method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#values) + - [onConflict method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#onConflict) + - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#returning) + - [insertInto method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#insertInto) +::: \ No newline at end of file diff --git a/site/docs/examples/JOIN/0010-simple-inner-join.mdx b/site/docs/examples/JOIN/0010-simple-inner-join.mdx index 0c024bb63..17ce8e62e 100644 --- a/site/docs/examples/JOIN/0010-simple-inner-join.mdx +++ b/site/docs/examples/JOIN/0010-simple-inner-join.mdx @@ -20,13 +20,13 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [innerJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#innerJoin) - - [leftJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#leftJoin) - - [rightJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#rightJoin) - - [fullJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#fullJoin) + - [innerJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#innerJoin) + - [leftJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#leftJoin) + - [rightJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#rightJoin) + - [fullJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#fullJoin) ::: \ No newline at end of file diff --git a/site/docs/examples/JOIN/0020-aliased-inner-join.mdx b/site/docs/examples/JOIN/0020-aliased-inner-join.mdx index ded5fb309..a16d0fb25 100644 --- a/site/docs/examples/JOIN/0020-aliased-inner-join.mdx +++ b/site/docs/examples/JOIN/0020-aliased-inner-join.mdx @@ -20,13 +20,13 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [innerJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#innerJoin) - - [leftJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#leftJoin) - - [rightJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#rightJoin) - - [fullJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#fullJoin) + - [innerJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#innerJoin) + - [leftJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#leftJoin) + - [rightJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#rightJoin) + - [fullJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#fullJoin) ::: \ No newline at end of file diff --git a/site/docs/examples/JOIN/0030-complex-join.js b/site/docs/examples/JOIN/0030-complex-join.js index 896320bb1..f4b9e4de3 100644 --- a/site/docs/examples/JOIN/0030-complex-join.js +++ b/site/docs/examples/JOIN/0030-complex-join.js @@ -4,6 +4,10 @@ export const complexJoin = `await db.selectFrom('person') (join) => join .onRef('pet.owner_id', '=', 'person.id') .on('pet.name', '=', 'Doggo') + .on((eb) => eb.or([ + eb('person.age', '>', 18), + eb('person.age', '<', 100) + ])) ) .selectAll() .execute()` \ No newline at end of file diff --git a/site/docs/examples/JOIN/0030-complex-join.mdx b/site/docs/examples/JOIN/0030-complex-join.mdx index 4d1dbd54b..564277e82 100644 --- a/site/docs/examples/JOIN/0030-complex-join.mdx +++ b/site/docs/examples/JOIN/0030-complex-join.mdx @@ -8,8 +8,10 @@ You can provide a function as the second argument to get a join builder for creating more complex joins. The join builder has a bunch of `on*` methods for building the `on` clause of the join. There's basically an equivalent for every `where` method -(`on`, `onRef` etc.). You can do all the same things with the -`on` method that you can with the corresponding `where` method. +(`on`, `onRef` etc.). + +You can do all the same things with the +`on` method that you can with the corresponding `where` method (like [OR expressions for example](https://kysely.dev/docs/examples/WHERE/or-where)). See the `where` method documentation for more examples. import { @@ -26,13 +28,13 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [innerJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#innerJoin) - - [leftJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#leftJoin) - - [rightJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#rightJoin) - - [fullJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#fullJoin) + - [innerJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#innerJoin) + - [leftJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#leftJoin) + - [rightJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#rightJoin) + - [fullJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#fullJoin) ::: \ No newline at end of file diff --git a/site/docs/examples/JOIN/0040-subquery-join.mdx b/site/docs/examples/JOIN/0040-subquery-join.mdx index d623ee678..2bc1ee0a1 100644 --- a/site/docs/examples/JOIN/0040-subquery-join.mdx +++ b/site/docs/examples/JOIN/0040-subquery-join.mdx @@ -20,13 +20,13 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [innerJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#innerJoin) - - [leftJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#leftJoin) - - [rightJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#rightJoin) - - [fullJoin method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#fullJoin) + - [innerJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#innerJoin) + - [leftJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#leftJoin) + - [rightJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#rightJoin) + - [fullJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#fullJoin) ::: \ No newline at end of file diff --git a/site/docs/examples/SELECT/0010-a-single-column.mdx b/site/docs/examples/SELECT/0010-a-single-column.mdx index 7a4b7277e..005bd0771 100644 --- a/site/docs/examples/SELECT/0010-a-single-column.mdx +++ b/site/docs/examples/SELECT/0010-a-single-column.mdx @@ -20,12 +20,12 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [select method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select) - - [selectAll method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#selectAll) - - [selectFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#selectFrom) + - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select) + - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll) + - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom) ::: \ No newline at end of file diff --git a/site/docs/examples/SELECT/0020-column-with-a-table.mdx b/site/docs/examples/SELECT/0020-column-with-a-table.mdx index bb9564829..9035e2344 100644 --- a/site/docs/examples/SELECT/0020-column-with-a-table.mdx +++ b/site/docs/examples/SELECT/0020-column-with-a-table.mdx @@ -20,12 +20,12 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [select method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select) - - [selectAll method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#selectAll) - - [selectFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#selectFrom) + - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select) + - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll) + - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom) ::: \ No newline at end of file diff --git a/site/docs/examples/SELECT/0030-multiple-columns.mdx b/site/docs/examples/SELECT/0030-multiple-columns.mdx index 1dabdb014..45cfebb64 100644 --- a/site/docs/examples/SELECT/0030-multiple-columns.mdx +++ b/site/docs/examples/SELECT/0030-multiple-columns.mdx @@ -20,12 +20,12 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [select method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select) - - [selectAll method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#selectAll) - - [selectFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#selectFrom) + - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select) + - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll) + - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom) ::: \ No newline at end of file diff --git a/site/docs/examples/SELECT/0040-aliases.js b/site/docs/examples/SELECT/0040-aliases.js index b2d2af633..6c81532f4 100644 --- a/site/docs/examples/SELECT/0040-aliases.js +++ b/site/docs/examples/SELECT/0040-aliases.js @@ -1,7 +1,7 @@ export const aliases = `const persons = await db - .selectFrom('person') + .selectFrom('person as p') .select([ 'first_name as fn', - 'person.last_name as ln' + 'p.last_name as ln' ]) .execute()` \ No newline at end of file diff --git a/site/docs/examples/SELECT/0040-aliases.mdx b/site/docs/examples/SELECT/0040-aliases.mdx index 2ac972434..980b20282 100644 --- a/site/docs/examples/SELECT/0040-aliases.mdx +++ b/site/docs/examples/SELECT/0040-aliases.mdx @@ -4,7 +4,7 @@ title: 'Aliases' # Aliases -You can provide an alias for the selections by appending `as the_alias` to the selection. +You can give an alias for selections and tables by appending `as the_alias` to the name: import { Playground, @@ -20,12 +20,12 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [select method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select) - - [selectAll method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#selectAll) - - [selectFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#selectFrom) + - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select) + - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll) + - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom) ::: \ No newline at end of file diff --git a/site/docs/examples/SELECT/0050-complex-selections.js b/site/docs/examples/SELECT/0050-complex-selections.js index 1b99b9a7c..29683f72b 100644 --- a/site/docs/examples/SELECT/0050-complex-selections.js +++ b/site/docs/examples/SELECT/0050-complex-selections.js @@ -1,7 +1,7 @@ export const complexSelections = `import { sql } from 'kysely' const persons = await db.selectFrom('person') - .select(({ selectFrom, or, cmpr }) => [ + .select(({ eb, selectFrom, or }) => [ // Select a correlated subquery selectFrom('pet') .whereRef('person.id', '=', 'pet.owner_id') @@ -13,8 +13,8 @@ const persons = await db.selectFrom('person') // Build and select an expression using // the expression builder or([ - cmpr('first_name', '=', 'Jennifer'), - cmpr('first_name', '=', 'Arnold') + eb('first_name', '=', 'Jennifer'), + eb('first_name', '=', 'Arnold') ]).as('is_jennifer_or_arnold'), // Select a raw sql expression diff --git a/site/docs/examples/SELECT/0050-complex-selections.mdx b/site/docs/examples/SELECT/0050-complex-selections.mdx index 4dba673fc..4714a0a68 100644 --- a/site/docs/examples/SELECT/0050-complex-selections.mdx +++ b/site/docs/examples/SELECT/0050-complex-selections.mdx @@ -21,12 +21,12 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [select method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select) - - [selectAll method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#selectAll) - - [selectFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#selectFrom) + - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select) + - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll) + - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom) ::: \ No newline at end of file diff --git a/site/docs/examples/SELECT/0051-not-null.js b/site/docs/examples/SELECT/0051-not-null.js new file mode 100644 index 000000000..3f8e2685c --- /dev/null +++ b/site/docs/examples/SELECT/0051-not-null.js @@ -0,0 +1,26 @@ +export const notNull = `import { NotNull } from 'kysely' +import { jsonObjectFrom } from 'kysely/helpers/postgres' + +const persons = db + .selectFrom('person') + .select((eb) => [ + 'last_name', + // Let's assume we know the person has at least one + // pet. We can use the \`.$notNull()\` method to make + // the expression not null. You could just as well + // add \`pet\` to the \`$narrowType\` call below. + jsonObjectFrom( + eb.selectFrom('pet') + .selectAll() + .limit(1) + .whereRef('person.id', '=', 'pet.owner_id') + ).$notNull().as('pet') + ]) + .where('last_name', 'is not', null) + // $narrowType can be used to narrow the output type. + // The special \`NotNull\` type can be used to make a + // selection not null. You could add \`pet: NotNull\` + // here and omit the \`$notNull()\` call on it. + // Use whichever way you prefer. + .$narrowType<{ last_name: NotNull }>() + .execute()` \ No newline at end of file diff --git a/site/docs/examples/SELECT/0051-not-null.mdx b/site/docs/examples/SELECT/0051-not-null.mdx new file mode 100644 index 000000000..528856ddb --- /dev/null +++ b/site/docs/examples/SELECT/0051-not-null.mdx @@ -0,0 +1,37 @@ +--- +title: 'Not null' +--- + +# Not null + +Sometimes you can be sure something's not null but Kysely isn't able to infer +it. For example calling `where('last_name', 'is not', null)` doesn't make +`last_name` not null in the result type but unless you have other where statements +you can be sure it's never null. + +Kysely has a couple of helpers for dealing with these cases: `$notNull()` and `$narrowType`. +Both are used in the following example: + +import { + Playground, + exampleSetup, +} from '../../../src/components/Playground' + +import { + notNull +} from './0051-not-null' + +
+ +
+ +:::info More examples +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) +but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always +just one hover away! + +For example, check out these sections: + - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select) + - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll) + - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom) +::: \ No newline at end of file diff --git a/site/docs/examples/SELECT/0060-function-calls.js b/site/docs/examples/SELECT/0060-function-calls.js index 258890274..9a895b2d8 100644 --- a/site/docs/examples/SELECT/0060-function-calls.js +++ b/site/docs/examples/SELECT/0060-function-calls.js @@ -1,15 +1,39 @@ -export const functionCalls = `const result = await db.selectFrom('person') +export const functionCalls = `import { sql } from 'kysely' + +const result = await db.selectFrom('person') .innerJoin('pet', 'pet.owner_id', 'person.id') - .select(({ fn }) => [ + .select(({ fn, val, ref }) => [ 'person.id', // The \`fn\` module contains the most common // functions. fn.count('pet.id').as('pet_count'), - // You can call any function using the - // \`agg\` method - fn.agg('array_agg', ['pet.name']).as('pet_names') + // 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('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('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\`concat( + \${ref('first_name')}, + ' ', + \${ref('last_name')} + )\`.as('full_name') ]) .groupBy('person.id') .having((eb) => eb.fn.count('pet.id'), '>', 10) diff --git a/site/docs/examples/SELECT/0060-function-calls.mdx b/site/docs/examples/SELECT/0060-function-calls.mdx index 1e327647f..b5b82bc32 100644 --- a/site/docs/examples/SELECT/0060-function-calls.mdx +++ b/site/docs/examples/SELECT/0060-function-calls.mdx @@ -4,7 +4,9 @@ title: 'Function calls' # Function calls -This example uses the `fn` module to select some aggregates: +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`. import { Playground, @@ -20,12 +22,12 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [select method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select) - - [selectAll method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#selectAll) - - [selectFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#selectFrom) + - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select) + - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll) + - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom) ::: \ No newline at end of file diff --git a/site/docs/examples/SELECT/0070-distinct.mdx b/site/docs/examples/SELECT/0070-distinct.mdx index f79af9c23..2b834d286 100644 --- a/site/docs/examples/SELECT/0070-distinct.mdx +++ b/site/docs/examples/SELECT/0070-distinct.mdx @@ -20,12 +20,12 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [select method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select) - - [selectAll method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#selectAll) - - [selectFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#selectFrom) + - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select) + - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll) + - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom) ::: \ No newline at end of file diff --git a/site/docs/examples/SELECT/0080-distinct-on.mdx b/site/docs/examples/SELECT/0080-distinct-on.mdx index 180ae48b6..eddcd673f 100644 --- a/site/docs/examples/SELECT/0080-distinct-on.mdx +++ b/site/docs/examples/SELECT/0080-distinct-on.mdx @@ -18,12 +18,12 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [select method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select) - - [selectAll method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#selectAll) - - [selectFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#selectFrom) + - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select) + - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll) + - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom) ::: \ No newline at end of file diff --git a/site/docs/examples/SELECT/0090-all-columns.mdx b/site/docs/examples/SELECT/0090-all-columns.mdx index 759c48796..a9e40d313 100644 --- a/site/docs/examples/SELECT/0090-all-columns.mdx +++ b/site/docs/examples/SELECT/0090-all-columns.mdx @@ -20,12 +20,12 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [select method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select) - - [selectAll method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#selectAll) - - [selectFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#selectFrom) + - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select) + - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll) + - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom) ::: \ No newline at end of file diff --git a/site/docs/examples/SELECT/0100-all-columns-of-a-table.mdx b/site/docs/examples/SELECT/0100-all-columns-of-a-table.mdx index 0e8b11e42..c614c7178 100644 --- a/site/docs/examples/SELECT/0100-all-columns-of-a-table.mdx +++ b/site/docs/examples/SELECT/0100-all-columns-of-a-table.mdx @@ -20,12 +20,12 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [select method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select) - - [selectAll method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#selectAll) - - [selectFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#selectFrom) + - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select) + - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll) + - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom) ::: \ No newline at end of file diff --git a/site/docs/examples/SELECT/0110-nested-array.mdx b/site/docs/examples/SELECT/0110-nested-array.mdx index b396cb4c9..5c27f4e02 100644 --- a/site/docs/examples/SELECT/0110-nested-array.mdx +++ b/site/docs/examples/SELECT/0110-nested-array.mdx @@ -12,7 +12,8 @@ Please keep in mind that the helpers under the `kysely/helpers` folder, includin `jsonArrayFrom`, are not guaranteed to work with third party dialects. In order for them to work, the dialect must automatically parse the `json` data type into javascript JSON values like objects and arrays. Some dialects might simply return -the data as a JSON string. +the data as a JSON string. In these cases you can use the built in `ParseJSONResultsPlugin` +to parse the results. import { Playground, @@ -28,12 +29,12 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [select method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select) - - [selectAll method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#selectAll) - - [selectFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#selectFrom) + - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select) + - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll) + - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom) ::: \ No newline at end of file diff --git a/site/docs/examples/SELECT/0120-nested-object.mdx b/site/docs/examples/SELECT/0120-nested-object.mdx index 0d4bbbee9..576342bab 100644 --- a/site/docs/examples/SELECT/0120-nested-object.mdx +++ b/site/docs/examples/SELECT/0120-nested-object.mdx @@ -9,10 +9,11 @@ helpers for fetching nested objects and arrays in a single query. In this exampl use the `jsonObjectFrom` helper to fetch person's favorite pet along with the person's id. Please keep in mind that the helpers under the `kysely/helpers` folder, including -`jsonObjectFrom`, are not guaranteed to work with third party dialects. In order for +`jsonObjectFrom`, are not guaranteed to work with 3rd party dialects. In order for them to work, the dialect must automatically parse the `json` data type into javascript JSON values like objects and arrays. Some dialects might simply return -the data as a JSON string. +the data as a JSON string. In these cases you can use the built in `ParseJSONResultsPlugin` +to parse the results. import { Playground, @@ -28,12 +29,12 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [select method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#select) - - [selectAll method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#selectAll) - - [selectFrom method](https://kysely-org.github.io/kysely/classes/Kysely.html#selectFrom) + - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select) + - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll) + - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom) ::: \ No newline at end of file diff --git a/site/docs/examples/UPDATE/0010-single-row.mdx b/site/docs/examples/UPDATE/0010-single-row.mdx index d6a652cbc..cf478cf32 100644 --- a/site/docs/examples/UPDATE/0010-single-row.mdx +++ b/site/docs/examples/UPDATE/0010-single-row.mdx @@ -20,12 +20,12 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [set method](https://kysely-org.github.io/kysely/classes/UpdateQueryBuilder.html#set) - - [returning method](https://kysely-org.github.io/kysely/classes/UpdateQueryBuilder.html#returning) - - [updateTable method](https://kysely-org.github.io/kysely/classes/Kysely.html#updateTable) + - [set method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#set) + - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#returning) + - [updateTable method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#updateTable) ::: \ No newline at end of file diff --git a/site/docs/examples/UPDATE/0020-complex-values.js b/site/docs/examples/UPDATE/0020-complex-values.js new file mode 100644 index 000000000..3b88fee1e --- /dev/null +++ b/site/docs/examples/UPDATE/0020-complex-values.js @@ -0,0 +1,11 @@ +export const complexValues = `const result = await db + .updateTable('person') + .set((eb) => ({ + age: eb('age', '+', 1), + first_name: eb.selectFrom('pet').select('name').limit(1), + last_name: 'updated', + })) + .where('id', '=', '1') + .executeTakeFirst() + +console.log(result.numUpdatedRows)` \ No newline at end of file diff --git a/site/docs/examples/UPDATE/0020-complex-values.mdx b/site/docs/examples/UPDATE/0020-complex-values.mdx new file mode 100644 index 000000000..0af4af00a --- /dev/null +++ b/site/docs/examples/UPDATE/0020-complex-values.mdx @@ -0,0 +1,32 @@ +--- +title: 'Complex values' +--- + +# Complex values + +As always, you can provide a callback to the `set` method to get access +to an expression builder: + +import { + Playground, + exampleSetup, +} from '../../../src/components/Playground' + +import { + complexValues +} from './0020-complex-values' + +
+ +
+ +:::info More examples +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) +but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always +just one hover away! + +For example, check out these sections: + - [set method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#set) + - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#returning) + - [updateTable method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#updateTable) +::: \ No newline at end of file diff --git a/site/docs/examples/WHERE/0010-simple-where-clause.mdx b/site/docs/examples/WHERE/0010-simple-where-clause.mdx index 92ce12d25..b3e8a7911 100644 --- a/site/docs/examples/WHERE/0010-simple-where-clause.mdx +++ b/site/docs/examples/WHERE/0010-simple-where-clause.mdx @@ -20,11 +20,11 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [where method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#where) - - [whereRef method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#whereRef) + - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where) + - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef) ::: \ No newline at end of file diff --git a/site/docs/examples/WHERE/0020-where-in.mdx b/site/docs/examples/WHERE/0020-where-in.mdx index ca60001a5..ece41d1dd 100644 --- a/site/docs/examples/WHERE/0020-where-in.mdx +++ b/site/docs/examples/WHERE/0020-where-in.mdx @@ -20,11 +20,11 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [where method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#where) - - [whereRef method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#whereRef) + - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where) + - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef) ::: \ No newline at end of file diff --git a/site/docs/examples/WHERE/0030-object-filter.js b/site/docs/examples/WHERE/0030-object-filter.js new file mode 100644 index 000000000..86a952191 --- /dev/null +++ b/site/docs/examples/WHERE/0030-object-filter.js @@ -0,0 +1,8 @@ +export const objectFilter = `const persons = await db + .selectFrom('person') + .selectAll() + .where((eb) => eb.and({ + first_name: 'Jennifer', + last_name: eb.ref('first_name') + })) + .execute()` \ No newline at end of file diff --git a/site/docs/examples/WHERE/0030-object-filter.mdx b/site/docs/examples/WHERE/0030-object-filter.mdx new file mode 100644 index 000000000..0236dde6c --- /dev/null +++ b/site/docs/examples/WHERE/0030-object-filter.mdx @@ -0,0 +1,31 @@ +--- +title: 'Object filter' +--- + +# Object filter + +You can use the `and` function to create a simple equality +filter using an object + +import { + Playground, + exampleSetup, +} from '../../../src/components/Playground' + +import { + objectFilter +} from './0030-object-filter' + +
+ +
+ +:::info More examples +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) +but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always +just one hover away! + +For example, check out these sections: + - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where) + - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef) +::: \ No newline at end of file diff --git a/site/docs/examples/WHERE/0030-or-where.js b/site/docs/examples/WHERE/0030-or-where.js deleted file mode 100644 index 402a6d6ec..000000000 --- a/site/docs/examples/WHERE/0030-or-where.js +++ /dev/null @@ -1,14 +0,0 @@ -export const orWhere = `const persons = await db - .selectFrom('person') - .selectAll() - .where(({ or, and, cmpr }) => or([ - and([ - cmpr('first_name', '=', 'Jennifer'), - cmpr('last_name', '=', 'Aniston') - ]), - and([ - cmpr('first_name', '=', 'Sylvester'), - cmpr('last_name', '=', 'Stallone') - ]) - ])) - .execute()` \ No newline at end of file diff --git a/site/docs/examples/WHERE/0040-conditional-where-calls.js b/site/docs/examples/WHERE/0040-conditional-where-calls.js deleted file mode 100644 index 31ddfb54f..000000000 --- a/site/docs/examples/WHERE/0040-conditional-where-calls.js +++ /dev/null @@ -1,18 +0,0 @@ -export const conditionalWhereCalls = `const firstName: string | undefined = 'Jennifer' -const lastName: string | undefined = 'Aniston' - -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) -} - -const persons = await query.execute()` \ No newline at end of file diff --git a/site/docs/examples/WHERE/0040-or-where.js b/site/docs/examples/WHERE/0040-or-where.js new file mode 100644 index 000000000..22c041f7e --- /dev/null +++ b/site/docs/examples/WHERE/0040-or-where.js @@ -0,0 +1,14 @@ +export const orWhere = `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()` \ No newline at end of file diff --git a/site/docs/examples/WHERE/0030-or-where.mdx b/site/docs/examples/WHERE/0040-or-where.mdx similarity index 60% rename from site/docs/examples/WHERE/0030-or-where.mdx rename to site/docs/examples/WHERE/0040-or-where.mdx index 3a98fac86..34f5c4209 100644 --- a/site/docs/examples/WHERE/0030-or-where.mdx +++ b/site/docs/examples/WHERE/0040-or-where.mdx @@ -4,7 +4,9 @@ title: 'OR where' # OR where -To combine conditions using `OR`, you can use the expression builder: +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: import { Playground, @@ -13,18 +15,18 @@ import { import { orWhere -} from './0030-or-where' +} from './0040-or-where'
:::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [where method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#where) - - [whereRef method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#whereRef) + - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where) + - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef) ::: \ No newline at end of file diff --git a/site/docs/examples/WHERE/0050-conditional-where-calls.js b/site/docs/examples/WHERE/0050-conditional-where-calls.js new file mode 100644 index 000000000..eec576155 --- /dev/null +++ b/site/docs/examples/WHERE/0050-conditional-where-calls.js @@ -0,0 +1,39 @@ +export const conditionalWhereCalls = `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[] = [] + + if (under18) { + ors.push(eb('age', '<', 18)) + } + + if (over60) { + ors.push(eb('age', '>', 60)) + } + + return eb.or(ors) + }) +} + +const persons = await query.execute()` \ No newline at end of file diff --git a/site/docs/examples/WHERE/0040-conditional-where-calls.mdx b/site/docs/examples/WHERE/0050-conditional-where-calls.mdx similarity index 66% rename from site/docs/examples/WHERE/0040-conditional-where-calls.mdx rename to site/docs/examples/WHERE/0050-conditional-where-calls.mdx index d9ae612e6..441ba3e11 100644 --- a/site/docs/examples/WHERE/0040-conditional-where-calls.mdx +++ b/site/docs/examples/WHERE/0050-conditional-where-calls.mdx @@ -13,18 +13,18 @@ import { import { conditionalWhereCalls -} from './0040-conditional-where-calls' +} from './0050-conditional-where-calls'
:::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [where method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#where) - - [whereRef method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#whereRef) + - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where) + - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef) ::: \ No newline at end of file diff --git a/site/docs/examples/WHERE/0050-complex-where-clause.js b/site/docs/examples/WHERE/0060-complex-where-clause.js similarity index 69% rename from site/docs/examples/WHERE/0050-complex-where-clause.js rename to site/docs/examples/WHERE/0060-complex-where-clause.js index cb9ebfde5..77d585f24 100644 --- a/site/docs/examples/WHERE/0050-complex-where-clause.js +++ b/site/docs/examples/WHERE/0060-complex-where-clause.js @@ -4,10 +4,10 @@ const maxAge = 60 const persons = await db .selectFrom('person') .selectAll('person') - .where(({ cmpr, or, and, not, exists, selectFrom }) => and([ + .where(({ eb, or, and, not, exists, selectFrom }) => and([ or([ - cmpr('first_name', '=', firstName), - cmpr('age', '<', maxAge) + eb('first_name', '=', firstName), + eb('age', '<', maxAge) ]), not(exists( selectFrom('pet') diff --git a/site/docs/examples/WHERE/0050-complex-where-clause.mdx b/site/docs/examples/WHERE/0060-complex-where-clause.mdx similarity index 69% rename from site/docs/examples/WHERE/0050-complex-where-clause.mdx rename to site/docs/examples/WHERE/0060-complex-where-clause.mdx index 118f3daec..876d9aa54 100644 --- a/site/docs/examples/WHERE/0050-complex-where-clause.mdx +++ b/site/docs/examples/WHERE/0060-complex-where-clause.mdx @@ -14,18 +14,18 @@ import { import { complexWhereClause -} from './0050-complex-where-clause' +} from './0060-complex-where-clause'
:::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [where method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#where) - - [whereRef method](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#whereRef) + - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where) + - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef) ::: \ No newline at end of file diff --git a/site/docs/examples/cte/0010-simple-selects.js b/site/docs/examples/cte/0010-simple-selects.js new file mode 100644 index 000000000..607b1b6ff --- /dev/null +++ b/site/docs/examples/cte/0010-simple-selects.js @@ -0,0 +1,21 @@ +export const simpleSelects = `const result = await db + // Create a CTE called \`jennifers\` that selects all + // persons named 'Jennifer'. + .with('jennifers', (db) => db + .selectFrom('person') + .where('first_name', '=', 'Jennifer') + .select(['id', 'age']) + ) + // Select all rows from the \`jennifers\` CTE and + // further filter it. + .with('adult_jennifers', (db) => db + .selectFrom('jennifers') + .where('age', '>', 18) + .select(['id', 'age']) + ) + // Finally select all adult jennifers that are + // also younger than 60. + .selectFrom('adult_jennifers') + .where('age', '<', 60) + .selectAll() + .execute()` \ No newline at end of file diff --git a/site/docs/examples/cte/0010-simple-selects.mdx b/site/docs/examples/cte/0010-simple-selects.mdx new file mode 100644 index 000000000..bdefb20e6 --- /dev/null +++ b/site/docs/examples/cte/0010-simple-selects.mdx @@ -0,0 +1,27 @@ +--- +title: 'Simple selects' +--- + +# Simple selects + +Common table expressions (CTE) are a great way to modularize complex queries. +Essentially they allow you to run multiple separate queries within a +single roundtrip to the DB. + +Since CTEs are a part of the main query, query optimizers inside DB +engines are able to optimize the overall query. For example, postgres +is able to inline the CTEs inside the using queries if it decides it's +faster. + +import { + Playground, + exampleSetup, +} from '../../../src/components/Playground' + +import { + simpleSelects +} from './0010-simple-selects' + +
+ +
diff --git a/site/docs/examples/cte/0020-inserts-updates-and-deletions.js b/site/docs/examples/cte/0020-inserts-updates-and-deletions.js new file mode 100644 index 000000000..e0eb6a67c --- /dev/null +++ b/site/docs/examples/cte/0020-inserts-updates-and-deletions.js @@ -0,0 +1,28 @@ +export const insertsUpdatesAndDeletions = `const result = await db + .with('new_person', (db) => db + .insertInto('person') + .values({ + first_name: 'Jennifer', + age: 35, + }) + .returning('id') + ) + .with('new_pet', (db) => db + .insertInto('pet') + .values({ + name: 'Doggo', + species: 'dog', + is_favorite: true, + // Use the id of the person we just inserted. + owner_id: db + .selectFrom('new_person') + .select('id') + }) + .returning('id') + ) + .selectFrom(['new_person', 'new_pet']) + .select([ + 'new_person.id as person_id', + 'new_pet.id as pet_id' + ]) + .execute()` \ No newline at end of file diff --git a/site/docs/examples/cte/0020-inserts-updates-and-deletions.mdx b/site/docs/examples/cte/0020-inserts-updates-and-deletions.mdx new file mode 100644 index 000000000..985247e75 --- /dev/null +++ b/site/docs/examples/cte/0020-inserts-updates-and-deletions.mdx @@ -0,0 +1,21 @@ +--- +title: 'Inserts, updates and deletions' +--- + +# Inserts, updates and deletions + +Some databases like postgres also allow you to run other queries than selects +in CTEs. On these databases CTEs are extremely powerful: + +import { + Playground, + exampleSetup, +} from '../../../src/components/Playground' + +import { + insertsUpdatesAndDeletions +} from './0020-inserts-updates-and-deletions' + +
+ +
diff --git a/site/docs/examples/cte/_category_.json b/site/docs/examples/cte/_category_.json new file mode 100644 index 000000000..aac3ee4bc --- /dev/null +++ b/site/docs/examples/cte/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "CTE", + "position": 7, + "link": { + "type": "generated-index", + "description": "Short and simple examples of how to use common table expressions (CTE) in queries." + } +} diff --git a/site/docs/examples/transactions/0010-simple-transaction.js b/site/docs/examples/transactions/0010-simple-transaction.js index c34ca9279..c7bc28ad7 100644 --- a/site/docs/examples/transactions/0010-simple-transaction.js +++ b/site/docs/examples/transactions/0010-simple-transaction.js @@ -12,7 +12,8 @@ export const simpleTransaction = `const catto = await db.transaction().execute(a .values({ owner_id: jennifer.id, name: 'Catto', - species: 'cat' + species: 'cat', + is_favorite: false, }) .returningAll() .executeTakeFirst() diff --git a/site/docs/examples/transactions/0010-simple-transaction.mdx b/site/docs/examples/transactions/0010-simple-transaction.mdx index 34458e124..514b1dc07 100644 --- a/site/docs/examples/transactions/0010-simple-transaction.mdx +++ b/site/docs/examples/transactions/0010-simple-transaction.mdx @@ -22,10 +22,10 @@ import { :::info More examples -The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely/) +The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/) but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always just one hover away! For example, check out these sections: - - [transaction method](https://kysely-org.github.io/kysely/classes/Kysely.html#transaction) + - [transaction method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#transaction) ::: \ No newline at end of file diff --git a/site/docs/generating-types.md b/site/docs/generating-types.md index bc359b9cb..734b64249 100644 --- a/site/docs/generating-types.md +++ b/site/docs/generating-types.md @@ -14,4 +14,12 @@ generates Kysely database schema type definitions by connecting to and introspec your database. This library works with all built-in dialects. - [prisma-kysely](https://github.com/valtyr/prisma-kysely) - This library generates -Kysely database schema type definitions from your existing Prisma schemas. \ No newline at end of file +Kysely database schema type definitions from your existing Prisma schemas. + +- [kanel-kysely](https://github.com/kristiandupont/kanel/tree/main/packages/kanel-kysely) - This +library generates Kysely database schema type definitions by connecting to and introspecting +your database. This library extends Kanel which is a mature PostgreSQL-only type generator. + +- [kysely-schema-generator](https://github.com/deanc/kysely-schema-generator) - This library +generates Kysely database schema type definitions by connecting to and introspecting +your database. Current MySQL only. diff --git a/site/docs/getting-started/Dialects.tsx b/site/docs/getting-started/Dialects.tsx index 251e86dd0..bdb2e2400 100644 --- a/site/docs/getting-started/Dialects.tsx +++ b/site/docs/getting-started/Dialects.tsx @@ -7,10 +7,11 @@ import TabItem from '@theme/TabItem' import Tabs from '@theme/Tabs' import { IUseADifferentPackageManager } from './IUseADifferentPackageManager' import { - DRIVER_NPM_PACKAGE_NAMES, + getDriverNPMPackageNames, getBashCommand, getDenoCommand, isDialectSupported, + POOL_NPM_PACKAGE_NAMES, PRETTY_DIALECT_NAMES, PRETTY_PACKAGE_MANAGER_NAMES, type Dialect, @@ -25,6 +26,7 @@ export interface DialectsProps { interface BuiltInDialect { value: Dialect driverDocsURL: string + poolDocsURL?: string } const builtInDialects: BuiltInDialect[] = [ @@ -37,6 +39,11 @@ const builtInDialects: BuiltInDialect[] = [ driverDocsURL: 'https://github.com/sidorares/node-mysql2/tree/master/documentation', }, + { + value: 'mssql', + driverDocsURL: 'https://tediousjs.github.io/tedious/index.html', + poolDocsURL: 'https://github.com/vincit/tarn.js', + }, { value: 'sqlite', driverDocsURL: @@ -55,9 +62,10 @@ export function Dialects(props: DialectsProps) { it. This requires a Dialect implementation.

- There are 3 built-in Node.js dialects for PostgreSQL, MySQL and SQLite. - Additionally, the community has implemented several dialects to choose - from. Find out more at "Dialects". + There are 4 built-in dialects for PostgreSQL, MySQL, Microsoft SQL + Server (MSSQL), and SQLite. Additionally, the community has implemented + several dialects to choose from. Find out more at{' '} + "Dialects".

Driver installation

@@ -67,8 +75,9 @@ export function Dialects(props: DialectsProps) {

{/* @ts-ignore For some odd reason, Tabs doesn't accept children in this file. */} - {builtInDialects.map(({ driverDocsURL, value }) => { - const driverNPMPackage = DRIVER_NPM_PACKAGE_NAMES[value] + {builtInDialects.map(({ driverDocsURL, poolDocsURL, value }) => { + const driverNPMPackage = getDriverNPMPackageNames()[value] + const poolNPMPackage = POOL_NPM_PACKAGE_NAMES[value] const prettyDialectName = PRETTY_DIALECT_NAMES[value] const installationCommand = packageManager === 'deno' @@ -77,7 +86,9 @@ export function Dialects(props: DialectsProps) { [`${driverNPMPackage}-pool`]: driverNPMPackage === 'pg' ? 'npm:pg-pool' : undefined, }) - : getBashCommand(packageManager, driverNPMPackage) + : getBashCommand(packageManager, driverNPMPackage, [ + poolNPMPackage, + ]) return ( // @ts-ignore For some odd reason, TabItem doesn't accept children in this file. @@ -97,6 +108,15 @@ export function Dialects(props: DialectsProps) { official documentation for configuration options.

+ {poolNPMPackage ? ( +

+ Additionally, Kysely's {prettyDialectName} dialect uses + the "{poolNPMPackage}" resource pool package for + connection pooling. Please refer to its{' '} + official documentation for + configuration options. +

+ ) : null}

{installationCommand.intro}

@@ -116,8 +136,8 @@ export function Dialects(props: DialectsProps) { Kysely can also work in compile-only mode that doesn't require a database driver. Find out more at{' '} - - "Splitting build, compile and execute code" + + "Splitting query building and execution" . diff --git a/site/docs/getting-started/Installation.tsx b/site/docs/getting-started/Installation.tsx index 0946011ef..9bdfba65f 100644 --- a/site/docs/getting-started/Installation.tsx +++ b/site/docs/getting-started/Installation.tsx @@ -29,13 +29,11 @@ const packageManagers: PackageManagerDetails[] = [ value: 'npm', description: ( <> - - {PRETTY_PACKAGE_MANAGER_NAMES['npm']} - {' '} + {PRETTY_PACKAGE_MANAGER_NAMES.npm}{' '} is the default package manager for , and to where Kysely is published.
- Your project is using {PRETTY_PACKAGE_MANAGER_NAMES['npm']} if it has a{' '} + Your project is using {PRETTY_PACKAGE_MANAGER_NAMES.npm} if it has a{' '} package-lock.json file in its root folder. ), @@ -45,11 +43,11 @@ const packageManagers: PackageManagerDetails[] = [ value: 'pnpm', description: ( <> - {PRETTY_PACKAGE_MANAGER_NAMES['pnpm']}{' '} - is a fast, disk space efficient package manager for + {PRETTY_PACKAGE_MANAGER_NAMES.pnpm} is + a fast, disk space efficient package manager for .
- Your project is using {PRETTY_PACKAGE_MANAGER_NAMES['pnpm']} if it has a{' '} + Your project is using {PRETTY_PACKAGE_MANAGER_NAMES.pnpm} if it has a{' '} pnpm-lock.yaml file in its root folder. ), @@ -60,12 +58,12 @@ const packageManagers: PackageManagerDetails[] = [ description: ( <> - {PRETTY_PACKAGE_MANAGER_NAMES['yarn']} + {PRETTY_PACKAGE_MANAGER_NAMES.yarn} {' '} is a fast, reliable and secure dependency manager for .
- Your project is using {PRETTY_PACKAGE_MANAGER_NAMES['yarn']} if it has a{' '} + Your project is using {PRETTY_PACKAGE_MANAGER_NAMES.yarn} if it has a{' '} yarn.lock file in its root folder. ), @@ -76,7 +74,7 @@ const packageManagers: PackageManagerDetails[] = [ description: ( <> - {PRETTY_PACKAGE_MANAGER_NAMES['deno']} + {PRETTY_PACKAGE_MANAGER_NAMES.deno} {' '} is a secure runtime for and{' '} TypeScript. @@ -88,10 +86,9 @@ const packageManagers: PackageManagerDetails[] = [ value: 'bun', description: ( <> - {PRETTY_PACKAGE_MANAGER_NAMES['bun']}{' '} - is a new runtime built for speed, with a native - bundler, transpiler, test runner, and{' '} - {PRETTY_PACKAGE_MANAGER_NAMES['npm']} + {PRETTY_PACKAGE_MANAGER_NAMES.bun} is a + new runtime built for speed, with a native bundler, + transpiler, test runner, and {PRETTY_PACKAGE_MANAGER_NAMES.npm} -compatible package manager baked-in. ), diff --git a/site/docs/getting-started/Instantiation.tsx b/site/docs/getting-started/Instantiation.tsx index ecad582a7..f837f8116 100644 --- a/site/docs/getting-started/Instantiation.tsx +++ b/site/docs/getting-started/Instantiation.tsx @@ -4,38 +4,61 @@ import CodeBlock from '@theme/CodeBlock' import { IUseADifferentDatabase } from './IUseADifferentDatabase' import { IUseADifferentPackageManager } from './IUseADifferentPackageManager' import { - DRIVER_NPM_PACKAGE_NAMES, + getDriverNPMPackageNames, isDialectSupported, + POOL_NPM_PACKAGE_NAMES, PRETTY_PACKAGE_MANAGER_NAMES, type Dialect, type PackageManager, type PropsWithDialect, + DIALECT_CLASS_NAMES, + PRETTY_DIALECT_NAMES, } from './shared' -const dialectSpecificCodeSnippets: Record< - Dialect, - (packageManager: PackageManager) => string | ReactNode -> = { - postgresql: (packageManager) => `import { Pool } from '${ - packageManager === 'deno' ? 'pg-pool' : DRIVER_NPM_PACKAGE_NAMES.postgresql - }' -import { Kysely, PostgresDialect } from 'kysely' - -const dialect = new PostgresDialect({ - pool: new Pool({ +function getNotSupportedCode( + dialect: Dialect, + packageManager: PackageManager +): string { + return `/* Kysely doesn't support ${PRETTY_DIALECT_NAMES[dialect]} + ${ + PRETTY_PACKAGE_MANAGER_NAMES[packageManager || 'npm'] + } out of the box. Import a community dialect that does here. */ +import { Kysely } from 'kysely' + +const dialect = /* instantiate the dialect here */` +} + +function getDialectSpecificCodeSnippet( + dialect: Dialect, + packageManager: PackageManager +): string { + const driverNPMPackageName = getDriverNPMPackageNames(packageManager)[dialect] + const dialectClassName = DIALECT_CLASS_NAMES[dialect] + const poolClassName = 'Pool' + const poolClassImport = packageManager === 'deno' ? poolClassName : `{ ${poolClassName} }` + + if (dialect === 'postgresql') { + return `import ${poolClassImport} from '${driverNPMPackageName}' +import { Kysely, ${dialectClassName} } from 'kysely' + +const dialect = new ${dialectClassName}({ + pool: new ${poolClassName}({ database: 'test', host: 'localhost', user: 'admin', port: 5434, max: 10, }) -})`, - mysql: - () => `import { createPool } from '${DRIVER_NPM_PACKAGE_NAMES.mysql}' // do not use 'mysql2/promises'! -import { Kysely, MysqlDialect } from 'kysely' +})` + } + + if (dialect === 'mysql') { + const poolFactoryName = 'createPool' -const dialect = new MysqlDialect({ - pool: createPool({ + return `import { ${poolFactoryName} } from '${driverNPMPackageName}' // do not use 'mysql2/promises'! +import { Kysely, ${dialectClassName} } from 'kysely' + +const dialect = new ${dialectClassName}({ + pool: ${poolFactoryName}({ database: 'test', host: 'localhost', user: 'admin', @@ -43,31 +66,57 @@ const dialect = new MysqlDialect({ port: 3308, connectionLimit: 10, }) -})`, - sqlite: (packageManager) => - isDialectSupported('sqlite', packageManager) - ? `import * as SQLite from '${DRIVER_NPM_PACKAGE_NAMES.sqlite}' -import { Kysely, SQLiteDialect } from 'kysely' - -const dialect = new SQLiteDialect({ - database: new SQLite(':memory:'), })` - : `/* Kysely doesn't support SQLite + ${ - PRETTY_PACKAGE_MANAGER_NAMES[packageManager || 'npm'] - } out of the box. Import a community dialect that does here. */ -import { Kysely } from 'kysely' + } -const dialect = /* instantiate the dialect here */`, -} + if (dialect === 'mssql') { + const poolPackageName = POOL_NPM_PACKAGE_NAMES.mssql + + return `import * as ${driverNPMPackageName} from '${driverNPMPackageName}' +import * as ${poolPackageName} from '${poolPackageName}' +import { Kysely, ${dialectClassName} } from 'kysely' + +const dialect = new ${dialectClassName}({ + ${poolPackageName}: { + ...${poolPackageName}, + options: { + min: 0, + max: 10, + }, + }, + ${driverNPMPackageName}: { + ...${driverNPMPackageName}, + connectionFactory: () => new ${driverNPMPackageName}.Connection({ + authentication: { + options: { + password: 'password', + userName: 'username', + }, + type: 'default', + }, + options: { + database: 'some_db', + port: 1433, + trustServerCertificate: true, + }, + server: 'localhost', + }), + }, +})` + } + + if (dialect === 'sqlite') { + const driverImportName = 'SQLite' -const dialectClassNames: Record< - Dialect, - (packageManager: PackageManager) => string | null -> = { - postgresql: () => 'PostgresDialect', - mysql: () => 'MysqlDialect', - sqlite: (packageManager) => - isDialectSupported('sqlite', packageManager) ? 'SQLiteDialect' : null, + return `import ${driverImportName} from '${driverNPMPackageName}' +import { Kysely, ${dialectClassName} } from 'kysely' + +const dialect = new ${dialectClassName}({ + database: new ${driverImportName}(':memory:'), +})` + } + + throw new Error(`Unsupported dialect: ${dialect}`) } export function Instantiation( @@ -79,15 +128,19 @@ export function Instantiation( const dialect = props.dialect || 'postgresql' const packageManager = props.packageManager || 'npm' - const dialectSpecificCodeSnippet = - dialectSpecificCodeSnippets[dialect](packageManager) - const dialectClassName = dialectClassNames[dialect](packageManager) + const dialectSpecificCodeSnippet = !isDialectSupported( + dialect, + packageManager + ) + ? getNotSupportedCode(dialect, packageManager) + : getDialectSpecificCodeSnippet(dialect, packageManager) + const dialectClassName = DIALECT_CLASS_NAMES[dialect] return ( <>

Let's create a Kysely instance - {dialectClassName ? ( + {isDialectSupported(dialect, packageManager) ? ( <> using the built-in {dialectClassName} diff --git a/site/docs/getting-started/Querying.tsx b/site/docs/getting-started/Querying.tsx index 737c0af32..af890ebcc 100644 --- a/site/docs/getting-started/Querying.tsx +++ b/site/docs/getting-started/Querying.tsx @@ -12,7 +12,7 @@ const postgresqlCodeSnippet = `export async function createPerson(person: NewPer .executeTakeFirstOrThrow() } -export async function deletePerson(id: Person['id']) { +export async function deletePerson(id: number) { return await db.deleteFrom('person').where('id', '=', id) .returningAll() .executeTakeFirst() @@ -24,11 +24,36 @@ const dialectSpecificCodeSnippets: Record = { const { insertId } = await db.insertInto('person') .values(person) .executeTakeFirstOrThrow() - - return await findPersonById(insertId) + + return await findPersonById(Number(insertId!)) +} + +export async function deletePerson(id: number) { + const person = await findPersonById(id) + + if (person) { + await db.deleteFrom('person').where('id', '=', id).execute() + } + + return person +}`, + mssql: `// As of v0.27.0, Kysely doesn't support the \`OUTPUT\` clause. This will change +// in the future. For now, the following implementations achieve the same results +// as other dialects' examples, but with extra steps. + +export async function createPerson(person: NewPerson) { + const compiledQuery = db.insertInto('person').values(person).compile() + + compiledQuery.sql += '; select scope_identity() as id' + + const { + rows: [{ id }], + } = await db.executeQuery>(compiledQuery) + + return await findPersonById(id) } -export async function deletePerson(id: Person['id']) { +export async function deletePerson(id: number) { const person = await findPersonById(id) if (person) { @@ -38,6 +63,7 @@ export async function deletePerson(id: Person['id']) { return person }`, sqlite: postgresqlCodeSnippet, + // TODO: Update to use output clause once #687 is completed } export function Querying(props: PropsWithDialect) { @@ -52,9 +78,9 @@ export function Querying(props: PropsWithDialect) {

{`import { db } from './database' -import { EditedPerson, Person, NewPerson } from './types' +import { PersonUpdate, Person, NewPerson } from './types' -export async function findPersonById(id: Person['id']) { +export async function findPersonById(id: number) { return await db.selectFrom('person') .where('id', '=', id) .selectAll() @@ -62,7 +88,7 @@ export async function findPersonById(id: Person['id']) { } export async function findPeople(criteria: Partial) { - const query = db.selectFrom('person') + let query = db.selectFrom('person') if (criteria.id) { query = query.where('id', '=', criteria.id) // Kysely is immutable, you must re-assign! @@ -74,8 +100,8 @@ export async function findPeople(criteria: Partial) { if (criteria.last_name !== undefined) { query = query.where( - 'last_name', - criteria.last_name === null ? 'is' : '=', + 'last_name', + criteria.last_name === null ? 'is' : '=', criteria.last_name ) } @@ -91,7 +117,7 @@ export async function findPeople(criteria: Partial) { return await query.selectAll().execute() } -export async function updatePerson(id: Person['id'], updateWith: EditedPerson) { +export async function updatePerson(id: number, updateWith: PersonUpdate) { await db.updateTable('person').set(updateWith).where('id', '=', id).execute() } diff --git a/site/docs/getting-started/Summary.tsx b/site/docs/getting-started/Summary.tsx index 05bf2cd46..3ed5b8557 100644 --- a/site/docs/getting-started/Summary.tsx +++ b/site/docs/getting-started/Summary.tsx @@ -28,22 +28,40 @@ const dialectSpecificCodeSnippets: Record = { cb.notNull().defaultTo(sql\`now()\`) ) .execute()`, + // TODO: Update line 42's IDENTITY once identity(1,1) is added to core. + mssql: ` await db.schema.createTable('person') + .addColumn('id', 'integer', (cb) => cb.primaryKey().modifyEnd(sql\`identity\`)) + .addColumn('first_name', 'varchar(255)', (cb) => cb.notNull()) + .addColumn('last_name', 'varchar(255)') + .addColumn('gender', 'varchar(50)', (cb) => cb.notNull()) + .addColumn('created_at', 'datetime', (cb) => + cb.notNull().defaultTo(sql\`GETDATE()\`) + ) + .execute()`, sqlite: ` await db.schema.createTable('person') .addColumn('id', 'integer', (cb) => cb.primaryKey().autoIncrement().notNull()) .addColumn('first_name', 'varchar(255)', (cb) => cb.notNull()) .addColumn('last_name', 'varchar(255)') .addColumn('gender', 'varchar(50)', (cb) => cb.notNull()) - .addColumn('created_at', 'timestampz', (cb) => + .addColumn('created_at', 'timestamp', (cb) => cb.notNull().defaultTo(sql\`current_timestamp\`) ) .execute()`, } +const dialectSpecificTruncateSnippets: Record = { + postgresql: `await sql\`truncate table \${sql.table('person')}\`.execute(db)`, + mysql: `await sql\`truncate table \${sql.table('person')}\`.execute(db)`, + mssql: `await sql\`truncate table \${sql.table('person')}\`.execute(db)`, + sqlite: `await sql\`delete from \${sql.table('person')}\`.execute(db)`, +} + export function Summary(props: PropsWithDialect) { const dialect = props.dialect || 'postgresql' const dialectSpecificCodeSnippet = dialectSpecificCodeSnippets[dialect] - const prettyDialectName = PRETTY_DIALECT_NAMES[dialect] + const dialectSpecificTruncateSnippet = + dialectSpecificTruncateSnippets[dialect] return ( <> @@ -66,26 +84,26 @@ ${dialectSpecificCodeSnippet} }) afterEach(async () => { - await sql\`truncate table \${sql.table('person')}\`.execute(db) + ${dialectSpecificTruncateSnippet} }) after(async () => { await db.schema.dropTable('person').execute() }) - it('should find a person with a given id', () => { + it('should find a person with a given id', async () => { await PersonRepository.findPersonById(123) }) - it('should find all people named Arnold', () => { + it('should find all people named Arnold', async () => { await PersonRepository.findPeople({ first_name: 'Arnold' }) }) - it('should update gender of a person with a given id', () => { + it('should update gender of a person with a given id', async () => { await PersonRepository.updatePerson(123, { gender: 'woman' }) }) - it('should create a person', () => { + it('should create a person', async () => { await PersonRepository.createPerson({ first_name: 'Jennifer', last_name: 'Aniston', @@ -93,7 +111,7 @@ ${dialectSpecificCodeSnippet} }) }) - it('should delete a person with a given id', () => { + it('should delete a person with a given id', async () => { await PersonRepository.deletePerson(123) }) })`} diff --git a/site/docs/getting-started/_types.mdx b/site/docs/getting-started/_types.mdx index 18cd993ca..a2bde2695 100644 --- a/site/docs/getting-started/_types.mdx +++ b/site/docs/getting-started/_types.mdx @@ -6,13 +6,24 @@ values. **Let's define our first database interface:** ```ts title="src/types.ts" -import { ColumnType, Generated, Insertable, Selectable, Updatable } from 'kysely' +import { + ColumnType, + Generated, + Insertable, + JSONColumnType, + Selectable, + Updateable +} from 'kysely' export interface Database { person: PersonTable pet: PetTable } +// This interface describes the `person` table to Kysely. Table +// interfaces should only be used in the `Database` type above +// and never as a result type of a query!. See the `Person`, +// `NewPerson` and `PersonUpdate` types below. export interface PersonTable { // Columns that are generated by the database should be marked // using the `Generated` type. This way they are automatically @@ -33,14 +44,29 @@ export interface PersonTable { // a `Date`, can optionally be provided as a `string` in inserts and // can never be updated: created_at: ColumnType + + // You can specify JSON columns using the `JSONColumnType` wrapper. + // It is a shorthand for `ColumnType`, where T + // is the type of the JSON object/array retrieved from the database, + // and the insert and update types are always `string` since you're + // always stringifying insert/update values. + metadata: JSONColumnType<{ + login_at: string; + ip: string | null; + agent: string | null; + plan: 'free' | 'premium'; + }> } // You should not use the table schema interfaces directly. Instead, you should // use the `Selectable`, `Insertable` and `Updateable` wrappers. These wrappers // make sure that the correct types are used in each operation. -export type Person = Selectable -export type NewPerson = Insertable -export type EditedPerson = Updateable +// +// Most of the time you should trust the type inference and not use explicit +// types at all. These types can be useful when typing function arguments. +export type Person = Selectable +export type NewPerson = Insertable +export type PersonUpdate = Updateable export interface PetTable { id: Generated @@ -49,15 +75,24 @@ export interface PetTable { species: 'dog' | 'cat' } -export type Pet = Selectable -export type NewPet = Insertable -export type EditedPet = Updateable +export type Pet = Selectable +export type NewPet = Insertable +export type PetUpdate = Updateable ``` :::tip Codegen For production apps, it is recommended to automatically generate your Database -interface by introspecting your production database or Prisma schemas. Find out more at -["Generating types"](https://kysely.dev/docs/generating-types). +interface by introspecting your production database or Prisma schemas. Generated types +might differ in naming convention, internal order, etc. Find out more at ["Generating types"](https://kysely.dev/docs/generating-types). + +::: + +:::info Runtime types + +Kysely only deals with types in the typescript level. The runtime javascript types are decided +by the underlying 3rd party driver such as `pg` or `mysql2` and it's up to you to select the correct +typescript types in the database interface. Kysely never touches the runtime output types in +any way. Find out more at ["Data types"](https://kysely.dev/docs/recipes/data-types). ::: diff --git a/site/docs/getting-started/shared.tsx b/site/docs/getting-started/shared.tsx index 4a0bc8900..ba24dcddd 100644 --- a/site/docs/getting-started/shared.tsx +++ b/site/docs/getting-started/shared.tsx @@ -1,7 +1,7 @@ import React, { type ReactNode } from 'react' import packageJson from '../../package.json' -export type Dialect = 'postgresql' | 'mysql' | 'sqlite' +export type Dialect = 'postgresql' | 'mysql' | 'sqlite' | 'mssql' export type PropsWithDialect

= P & { dialect: Dialect | undefined @@ -12,8 +12,8 @@ export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'deno' | 'bun' const PACKAGE_MANAGER_UNSUPPORTED_DIALECTS: Record = { - bun: ['sqlite'], - deno: ['sqlite'], + bun: ['sqlite', 'mssql'], + deno: ['sqlite', 'mssql'], npm: [], pnpm: [], yarn: [], @@ -26,35 +26,48 @@ export function isDialectSupported( return !PACKAGE_MANAGER_UNSUPPORTED_DIALECTS[packageManager].includes(dialect) } -export const DRIVER_NPM_PACKAGE_NAMES: Record = { - postgresql: 'pg', - mysql: 'mysql2', - sqlite: 'better-sqlite3', -} +export const DIALECT_CLASS_NAMES = { + postgresql: 'PostgresDialect', + mysql: 'MysqlDialect', + mssql: 'MssqlDialect', + sqlite: 'SqliteDialect', +} as const satisfies Record + +export const getDriverNPMPackageNames = ( + packageManager: PackageManager = 'npm' +) => + ({ + postgresql: packageManager === 'deno' ? 'pg-pool' : 'pg', + mysql: 'mysql2', + mssql: 'tedious', + sqlite: 'better-sqlite3', + } as const satisfies Record) + +export const POOL_NPM_PACKAGE_NAMES = { + mssql: 'tarn', +} as const satisfies Partial> -export const PRETTY_DIALECT_NAMES: Record = { +export const PRETTY_DIALECT_NAMES = { postgresql: 'PostgreSQL', mysql: 'MySQL', + mssql: 'Microsoft SQL Server (MSSQL)', sqlite: 'SQLite', -} +} as const satisfies Record -export const PRETTY_PACKAGE_MANAGER_NAMES: Record = { +export const PRETTY_PACKAGE_MANAGER_NAMES = { npm: 'npm', pnpm: 'pnpm', yarn: 'Yarn', deno: 'Deno', bun: 'Bun', -} +} as const satisfies Record -const PACKAGE_MANAGER_INSTALL_COMMANDS: Record< - Exclude, - string -> = { +const PACKAGE_MANAGER_INSTALL_COMMANDS = { npm: 'npm install', pnpm: 'pnpm install', yarn: 'yarn add', bun: 'bun install', -} +} as const satisfies Omit, 'deno'> export interface Command { content: ReactNode @@ -65,14 +78,19 @@ export interface Command { export function getBashCommand( packageManager: PackageManager, - installedPackage: string + installedPackage: string, + additionalPackages?: string[] ): Command { if (packageManager === 'deno') { throw new Error('Deno has no bash command') } return { - content: `${PACKAGE_MANAGER_INSTALL_COMMANDS[packageManager]} ${installedPackage}`, + content: `${ + PACKAGE_MANAGER_INSTALL_COMMANDS[packageManager] + } ${installedPackage}${ + additionalPackages?.length ? ` ${additionalPackages.join(' ')}` : '' + }`, intro: 'Run the following command in your terminal:', language: 'bash', title: 'terminal', diff --git a/site/docs/intro.md b/site/docs/intro.md deleted file mode 100644 index b9c0ce525..000000000 --- a/site/docs/intro.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -sidebar_position: 1 ---- - -# Introduction - -Kysely (pronounced “Key-Seh-Lee”) is a type-safe and autocompletion-friendly TypeScript SQL query builder. Inspired by Knex. Mainly developed for Node.js but also runs on Deno and in the browser. - -![image](https://github.com/kysely-org/kysely/raw/master/assets/demo.gif) - -Kysely makes sure you only refer to tables and columns that are visible to the part of the query you're writing. The result type only has the selected columns with correct types and aliases. As an added bonus you get autocompletion for all that stuff. - -As shown above, through the magic of TypeScript, Kysely is able to parse the alias given to `pet.name` and add the `pet_name` column to the result row type. Kysely is able to infer column names, aliases and types from selected subqueries, joined subqueries, `with` statements and pretty much anything you can think of. - -Of course there are cases where things cannot be typed at compile time, and Kysely offers escape hatches for these situations. See the [sql](https://kysely-org.github.io/kysely/interfaces/Sql.html) template tag and the [DynamicModule](https://kysely-org.github.io/kysely/classes/DynamicModule.html) for more info. - -All API documentation is written in the typing files and you can simply cmd-click on the module, class or method you're using to see it. The same documentation is also hosted [here](https://kysely-org.github.io/kysely). - -## Looking for help? - -If you start using Kysely and can't find something you'd want to use, please [open an issue](https://github.com/kysely-org/kysely/issues) or [join our discord server](https://discord.gg/xyBJ3GwvAm). diff --git a/site/docs/intro.mdx b/site/docs/intro.mdx new file mode 100644 index 000000000..c4ea6f423 --- /dev/null +++ b/site/docs/intro.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 1 +--- + +import { DemoVideo } from '@site/src/components/DemoVideo' + +# Introduction + +Kysely (pronounced “Key-Seh-Lee”) is a type-safe and autocompletion-friendly TypeScript SQL query builder. Inspired by Knex. Mainly developed for [node.js](https://nodejs.org/en/) but also +runs on all other javascript environments like [deno](https://deno.land/) and [bun](https://bun.sh/). + + + +Kysely makes sure you only refer to tables and columns that are visible to the part of the query you're writing. The result type only has the selected columns with correct types and aliases. As an added bonus you get autocompletion for all that stuff. + +As shown in the gif above, through the pure magic of modern typescript, Kysely is even able to parse the alias given to `pet.name` and add the `pet_name` column to the result row type. Kysely is able to infer column names, aliases and types from selected subqueries, joined subqueries, `with` statements and pretty much anything you can think of. + +Of course there are cases where things cannot be typed at compile time, and Kysely offers escape hatches for these situations. See the [sql template tag](https://kysely-org.github.io/kysely-apidoc/interfaces/Sql.html) and the [DynamicModule](https://kysely-org.github.io/kysely-apidoc/classes/DynamicModule.html#ref) for more info. + +All API documentation is written in the typing files and you can simply hover over the module, class or method you're using to see it in your IDE. The same documentation is also hosted [here](https://kysely-org.github.io/kysely-apidoc/). + +If you start using Kysely and can't find something you'd want to use, please open an issue or join our [discord server](https://discord.gg/xyBJ3GwvAm). + +## Looking for help? + +If you start using Kysely and can't find something you'd want to use, please [open an issue](https://github.com/kysely-org/kysely/issues) or [join our discord server](https://discord.gg/xyBJ3GwvAm). diff --git a/site/docs/migrations.mdx b/site/docs/migrations.mdx index 2aa2ebde8..263b96add 100644 --- a/site/docs/migrations.mdx +++ b/site/docs/migrations.mdx @@ -26,7 +26,21 @@ Migrations can use the `Kysely.schema` module to modify the schema. Migrations c ## Execution order -Execution order of the migrations is the alpabetical order of their names. An excellent way to name your migrations is to prefix them with an ISO 8601 date string. A date prefix works well in large teams where multiple team members may add migrations at the same time in parallel commits without knowing about the other migrations. +Migrations will be run in the alpha-numeric order of your migration names. An excellent way to name your migrations is to prefix them with an ISO 8601 date string. + +By default, Kysely will also ensure this order matches the execution order of any previously executed migrations in your database. If the orders do not match (for example, a new migration was added alphabetically before a previously executed one), an error will be returned. This adds safety by always executing your migrations in the correct, alphanumeric order. + +There is also an `allowUnorderedMigrations` option. This option will allow new migrations to be run even if they are added alphabetically before ones that have already executed. Allowing unordered migrations works well in large teams where multiple team members may add migrations at the same time in parallel commits without knowing about the other migrations. Pending (unexecuted) migrations will be run in alpha-numeric order when migrating up. When migrating down, migrations will be undone in the opposite order in which they were executed (reverse sorted by execution timestamp). + +To allow unordered migrations, pass the `allowUnorderedMigrations` option to Migrator: + +```ts +const migrator = new Migrator({ + db, + provider: new FileMigrationProvider(...), + allowUnorderedMigrations: true +}) +``` ## Single file vs multiple file migrations @@ -72,6 +86,46 @@ export async function down(db: Kysely): Promise { } ``` +## SQLite migration example + +```ts +import { Kysely, sql } from 'kysely' + +export async function up(db: Kysely): Promise { + await db.schema + .createTable('person') + .addColumn('id', 'integer', (col) => col.primaryKey()) + .addColumn('first_name', 'text', (col) => col.notNull()) + .addColumn('last_name', 'text') + .addColumn('gender', 'text', (col) => col.notNull()) + .addColumn('created_at', 'text', (col) => + col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull() + ) + .execute() + + await db.schema + .createTable('pet') + .addColumn('id', 'integer', (col) => col.primaryKey()) + .addColumn('name', 'text', (col) => col.notNull().unique()) + .addColumn('owner_id', 'integer', (col) => + col.references('person.id').onDelete('cascade').notNull() + ) + .addColumn('species', 'text', (col) => col.notNull()) + .execute() + + await db.schema + .createIndex('pet_owner_id_index') + .on('pet') + .column('owner_id') + .execute() +} + +export async function down(db: Kysely): Promise { + await db.schema.dropTable('pet').execute() + await db.schema.dropTable('person').execute() +} +``` + ## Running migrations You can then use @@ -142,4 +196,4 @@ The migration methods use a lock on the database level and parallel calls are ex ## Reference documentation -[Migrator](https://kysely-org.github.io/kysely/classes/Migrator.html) +[Migrator](https://kysely-org.github.io/kysely-apidoc/classes/Migrator.html) diff --git a/site/docs/playground.mdx b/site/docs/playground.mdx index 1477cbca2..e9ec5f95d 100644 --- a/site/docs/playground.mdx +++ b/site/docs/playground.mdx @@ -4,7 +4,7 @@ sidebar_position: 3 # Playground -[@wirekang](https://github.com/wirekang) has created a [playground for Kysely](https://wirekang.github.io/kysely-playground/?p=f&i=-NLp3n_P5fyeQKMQda8n). You can use it to quickly test stuff out and for creating code examples for your issues, PRs and Discord messages. +[@wirekang](https://github.com/wirekang) has created a [playground for Kysely](https://kyse.link). You can use it to quickly test stuff out and for creating code examples for your issues, PRs and Discord messages. import { Playground, exampleFilterById } from '../src/components/Playground' diff --git a/site/docs/plugins.md b/site/docs/plugins.md index 5e5589061..f9f23230b 100644 --- a/site/docs/plugins.md +++ b/site/docs/plugins.md @@ -1,6 +1,6 @@ # Plugin system -Plugins are classes that implement [KyselyPlugin](https://kysely-org.github.io/kysely/interfaces/KyselyPlugin.html). Plugins are then added to the `Kysely` instance as follows: +Plugins are classes that implement [KyselyPlugin](https://kysely-org.github.io/kysely-apidoc/interfaces/KyselyPlugin.html). Plugins are then added to the `Kysely` instance as follows: ```ts const db = new Kysely({ @@ -16,8 +16,8 @@ const db = new Kysely({ ### Camel case plugin -A plugin that converts snake_case identifiers in the database into camelCase in the JavaScript side. [Learn more](https://kysely-org.github.io/kysely/classes/CamelCasePlugin.html). +A plugin that converts snake_case identifiers in the database into camelCase in the JavaScript side. [Learn more](https://kysely-org.github.io/kysely-apidoc/classes/CamelCasePlugin.html). ### Deduplicate joins plugin -Plugin that removes duplicate joins from queries. You can read more about it in the [examples](/docs/recipes/deduplicate-joins) section or check the [API docs](https://kysely-org.github.io/kysely/classes/DeduplicateJoinsPlugin.html). +Plugin that removes duplicate joins from queries. You can read more about it in the [examples](/docs/recipes/deduplicate-joins) section or check the [API docs](https://kysely-org.github.io/kysely-apidoc/classes/DeduplicateJoinsPlugin.html). diff --git a/site/docs/recipes/relations.md b/site/docs/recipes/0001-relations.md similarity index 63% rename from site/docs/recipes/relations.md rename to site/docs/recipes/0001-relations.md index 1c7186874..0e3d0c0f3 100644 --- a/site/docs/recipes/relations.md +++ b/site/docs/recipes/0001-relations.md @@ -7,13 +7,28 @@ Kysely IS a query builder. Kysely DOES build the SQL you tell it to, nothing mor Phew, glad we got that out the way.. -All that was said above doesn't mean there's no way to nest related rows in your queries. -You just have to do it with the tools SQL and the underlying dialect (e.g. PostgreSQL or MySQL) provide. -In this recipe we show one way to do that when using the built-in PostgreSQL and MySQL dialects. +Having said all that, there are ways to nest related rows in your queries. You just have to do it +using the tools SQL and the underlying dialect (e.g. PostgreSQL, MySQL, or SQLite) provide. In this recipe +we show one way to do that when using the built-in PostgreSQL, MySQL, and SQLite dialects. + +This recipe is supported on MySQL versions starting from 8.0.14. This is due to the way subqueries use outer references in this recipe (cf. [MySQL 8.0.14 changelog](https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-14.html#mysqld-8-0-14-optimizer) | [MariaDB is not supported yet](https://jira.mariadb.org/browse/MDEV-19078)). ## The `json` data type and functions -Both PostgreSQL and MySQL have rich JSON support through their `json` data types and functions. `pg` and `mysql2`, the node drivers, automatically parse returned `json` columns as json objects. With the combination of these two things, we can write some super efficient queries with nested relations. +PostgreSQL and MySQL have rich JSON support through their `json` data types and functions. `pg` and `mysql2`, the node drivers, automatically parse returned `json` columns as json objects. With the combination of these two things, we can write some super efficient queries with nested relations. + +:::info Parsing JSON +The built in `SqliteDialect` and some 3rd party dialects don't parse the returned JSON columns to objects automatically. +Not even if they use `PostgreSQL` or `MySQL` under the hood! Parsing is handled (or not handled) by the database driver +that Kysely has no control over. If your JSON columns get returned as strings, you can use the `ParseJSONResultsPlugin`: + +```ts +const db = new Kysely({ + ... + plugins: [new ParseJSONResultsPlugin()] +}) +``` +::: Let's start with some raw postgres SQL, and then see how we can write the query using Kysely in a nice type-safe way. @@ -25,32 +40,32 @@ SELECT -- Select person's pets as a json array ( - SELECT + SELECT COALESCE(JSON_AGG(pets), '[]') FROM ( - SELECT + SELECT pet.id, pet.name FROM pet - WHERE + WHERE pet.owner_id = person.id - ORDER BY + ORDER BY pet.name ) pets ) pets, -- Select person's mother as a json object ( - SELECT + SELECT TO_JSON(mother) FROM ( - SELECT + SELECT mother.id, mother.first_name FROM person as mother - WHERE + WHERE mother.id = person.mother_id ) mother ) mother @@ -82,12 +97,16 @@ These helpers are included in Kysely and you can import them from the `helpers` import { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/postgres' ``` -MySQL versions of the helpers are slightly different but you can use them the same way. You can import them like this: +MySQL and SQLite versions of the helpers are slightly different but you can use them the same way. You can import them like this: ```ts import { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/mysql' ``` +```ts +import { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/sqlite' +``` + With these helpers, our example query already becomes a little more bearable to look at: ```ts @@ -152,3 +171,14 @@ const persons = await db console.log(persons[0].pets[0].name) console.log(persons[0].mother.first_name) ``` + +If you need to select relations conditionally, `$if` is your friend: + +```ts +const persons = await db + .selectFrom('person') + .selectAll('person') + .$if(includePets, (qb) => qb.select(withPets)) + .$if(includeMom, (qb) => qb.select(withMom)) + .execute() +``` diff --git a/site/docs/recipes/0002-data-types.md b/site/docs/recipes/0002-data-types.md new file mode 100644 index 000000000..6f81c30fa --- /dev/null +++ b/site/docs/recipes/0002-data-types.md @@ -0,0 +1,80 @@ +# Data types + +When talking about data types in Kysely we need to make a distinction between the two kinds of types: + +1. Typescript types +2. Runtime javascript types + +## Typescript types + +In Kysely, you only define typescript types for your tables and columns. Since typescript is entirely a compile-time concept, typescript types __can't__ affect runtime javascript types. If you define your column to be a `string` in typescript but the database returns a `number`, the runtime type doesn't magically change to `string`. You'll see a `string` in the typescript code, but observe a number when you run the program. + +:::info +It's up to **you** to select correct typescript types for your columns based on what the driver returns. +::: + +## Runtime javascript types + +The database driver, such as `pg` or `mysql2`, decides the runtime javascript types the queries return. Kysely never touches the runtime types the driver returns. In fact, Kysely doesn't touch the data returned by the driver in any way. It simply executes the query and returns whatever the driver returns. An exception to this rule is when you use a plugin like `CamelCasePlugin`, in which case Kysely does change the column names. + +You need to read the underlying driver's documentation or otherwise figure out what the driver returns and then align the typescript types to match them. + +### Configuring runtime javascript types + +Most drivers provide a way to change the returned types. For example `pg` returns `bigint` and `numeric` types as strings by default, but often you want to configure it to return numbers instead. + +#### Postgres + +When using the `pg` driver, you can use the [pg-types](https://github.com/brianc/node-pg-types) package to configure the types. For example here's how you'd configure the `bigint` to be returned as a number: + +```ts +import { Kysely, PostgresDialect } from 'kysely' +import * as pg from 'pg' + +const int8TypeId = 20 +// Map int8 to number. +pg.types.setTypeParser(int8TypeId, (val) => { + return parseInt(val, 10) +}) + +export const db = new Kysely({ + dialect: new PostgresDialect({ + pool: new pg.Pool(config), + }), +}) +``` + +See the documentation [here](https://github.com/brianc/node-pg-types) on how to figure out the correct type id. + +#### MySQL + +When using the `mysql2` driver, you an use the [typeCast](https://github.com/mysqljs/mysql?tab=readme-ov-file#custom-type-casting) pool property. + +For example here's how you'd map `tinyint(1)` to a boolean: + +```ts +import { Kysely, MysqlDialect } from 'kysely' +import { createPool } from 'mysql2' + +export const db = new Kysely({ + dialect: new MysqlDialect({ + pool: createPool({ + ...config, + // Map tinyint(1) to boolean + typeCast(field, next) { + if (field.type === 'TINY' && field.length === 1) { + return field.string() === '1' + } else { + return next() + } + }, + }), + }), +}) +``` + +## Type generators + +There are 3rd party type generators such as [kysely-codegen](https://github.com/RobinBlomberg/kysely-codegen) and [kanel-kysely](https://kristiandupont.github.io/kanel/kanel-kysely.html) that automatically generate typescript types based on the database schema. Find out more at ["Generating types"](https://kysely.dev/docs/generating-types). + +If these tools generate a type that doesn't match the runtime type you observe, please refer to their documentation or open an issue in their github. Kysely has no control over these libraries. \ No newline at end of file diff --git a/site/docs/recipes/raw-sql.md b/site/docs/recipes/0003-raw-sql.md similarity index 85% rename from site/docs/recipes/raw-sql.md rename to site/docs/recipes/0003-raw-sql.md index 4d5c9eac6..210598f80 100644 --- a/site/docs/recipes/raw-sql.md +++ b/site/docs/recipes/0003-raw-sql.md @@ -1,4 +1,4 @@ # Raw SQL You can execute raw SQL strings and pass raw SQL snippets to pretty much any method or function -using the [sql template tag](https://kysely-org.github.io/kysely/interfaces/Sql.html). +using the [sql template tag](https://kysely-org.github.io/kysely-apidoc/interfaces/Sql.html). diff --git a/site/docs/recipes/splitting-build-compile-and-execute-code.md b/site/docs/recipes/0004-splitting-query-building-and-execution.md similarity index 86% rename from site/docs/recipes/splitting-build-compile-and-execute-code.md rename to site/docs/recipes/0004-splitting-query-building-and-execution.md index c3bf0da31..f0006f314 100644 --- a/site/docs/recipes/splitting-build-compile-and-execute-code.md +++ b/site/docs/recipes/0004-splitting-query-building-and-execution.md @@ -1,26 +1,36 @@ -# Splitting build, compile and execute code +# Splitting query building and execution Kysely is primarily a type-safe sql query builder. -It also does query execution, migrations, etc. in order to align with Knex's "batteries +It also does query execution, migrations, etc. in order to align with Knex's "batteries included" approach. ## "Cold" Kysely instances -In order to use Kysely purely as a query builder without database driver dependencies, +In order to use Kysely purely as a query builder without database driver dependencies, you can instantiate it with the built-in `DummyDriver` class: ```ts -import { +import { + Generated, DummyDriver, Kysely, PostgresAdapter, - PostgresCompiler, PostgresIntrospector, PostgresQueryCompiler, } from 'kysely' -const db = new Kysely({ +interface Person { + id: Generated + first_name: string + last_name: string | null +} + +interface Database { + person: Person +} + +const db = new Kysely({ dialect: { createAdapter: () => new PostgresAdapter(), createDriver: () => new DummyDriver(), @@ -30,12 +40,12 @@ const db = new Kysely({ }) ``` -This Kysely instance will compile to PostgreSQL sql dialect. You can brew "dummy" -dialects to compile to all kinds of sql dialects (e.g. MySQL). Trying to execute -queries using "cold" kysely instances will return empty results without communicating +This Kysely instance will compile to PostgreSQL sql dialect. You can brew "dummy" +dialects to compile to all kinds of sql dialects (e.g. MySQL). Trying to execute +queries using "cold" kysely instances will return empty results without communicating with a database. -> "Cold" Kysely instances are not required for the following sections. You can +> "Cold" Kysely instances are not required for the following sections. You can use "hot" kysely instances, with real drivers, if you want to. ## Compile a query @@ -52,11 +62,11 @@ const compiledQuery = db console.log(compiledQuery) // { sql: 'select "first_name" from "person" where "id" = $1', parameters: [1], query: { ... } } ``` -The result of `.compile()` is a `CompiledQuery` object. It contains the query string -(in `sql` field), parameters and the original Kysely-specific syntax tree used +The result of `.compile()` is a `CompiledQuery` object. It contains the query string +(in `sql` field), parameters and the original Kysely-specific syntax tree used for compilation. -This output alone can be used with any database driver that understands the sql +This output alone can be used with any database driver that understands the sql dialect used (PostgreSQL in this example). Raw queries can be compiled as well: @@ -71,8 +81,8 @@ console.log(compiledQuery) // { sql: 'select * from person where id = $1', param ## Infer result type -Kysely supports inferring a (compiled) query's result type even when detached from -query building chains. This allows splitting query building, compilation and execution +Kysely supports inferring a (compiled) query's result type even when detached from +query building chains. This allows splitting query building, compilation and execution code without losing type-safety. ```ts @@ -105,5 +115,5 @@ const compiledQuery = db const results = await db.executeQuery(compiledQuery) ``` -The `QueryResult` object returned by `.executeQuery()` contains the query results' +The `QueryResult` object returned by `.executeQuery()` contains the query results' rows, insertId and number of affected rows (if applicable). \ No newline at end of file diff --git a/site/docs/recipes/conditional-selects.md b/site/docs/recipes/0005-conditional-selects.md similarity index 91% rename from site/docs/recipes/conditional-selects.md rename to site/docs/recipes/0005-conditional-selects.md index 36b1bf554..41eb6fb12 100644 --- a/site/docs/recipes/conditional-selects.md +++ b/site/docs/recipes/0005-conditional-selects.md @@ -17,6 +17,7 @@ async function getPerson(id: number, withLastName: boolean) { let query = db.selectFrom('person').select('first_name').where('id', '=', id) if (withLastName) { + // ❌ The type of `query` doesn't change here query = query.select('last_name') } @@ -32,10 +33,12 @@ with `last_name` selection is `B` which extends `A` but also contains informatio about the new selection. When you assign an object of type `B` to `query` inside the `if` statement, the type gets downcast to `A`. -You can write code like this to add conditional `where`, `groupBy`, `orderBy` etc. +:::info +You _can_ write code like this to add conditional `where`, `groupBy`, `orderBy` etc. statements that don't change the type of the query builder, but it doesn't work with `select`, `returning`, `innerJoin` etc. that _do_ change the type of the query builder. +::: In this simple case you could implement the method like this: @@ -61,7 +64,7 @@ conditions the amount of code explodes if you want to keep things type-safe. You to create a separate branch for every possible combination of selections or otherwise the types won't be correct. -This is where the [$if](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#_if) +This is where the [$if](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#_if) method can help you: ```ts diff --git a/site/docs/recipes/expressions.md b/site/docs/recipes/0006-expressions.md similarity index 82% rename from site/docs/recipes/expressions.md rename to site/docs/recipes/0006-expressions.md index 87f8f9c88..b9dbaabcb 100644 --- a/site/docs/recipes/expressions.md +++ b/site/docs/recipes/0006-expressions.md @@ -1,12 +1,12 @@ # Expressions -An [`Expression`](https://kysely-org.github.io/kysely/interfaces/Expression.html) is the basic type-safe query building block in Kysely. Pretty much all methods accept expressions as inputs. Most internal classes like [SelectQueryBuilder](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html) and [RawBuilder](https://kysely-org.github.io/kysely/classes/RawBuilder.html) (the return value of the [sql tag](https://kysely-org.github.io/kysely/functions/sql-1.html)) are expressions themselves. +An [`Expression`](https://kysely-org.github.io/kysely-apidoc/interfaces/Expression.html) is the basic type-safe query building block in Kysely. Pretty much all methods accept expressions as inputs. Most internal classes like [SelectQueryBuilder](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html) and [RawBuilder](https://kysely-org.github.io/kysely-apidoc/interfaces/RawBuilder.html) (the return value of the [sql tag](https://kysely-org.github.io/kysely-apidoc/functions/sql-1.html)) are expressions themselves. `Expression` represents an arbitrary SQL expression, like a binary expression (e.g. `a + b`), or a function call (e.g. `concat(arg1, ' ', arg2, ...)`). It can be any combination of those, no matter how complex. `T` is the output type of the expression. ## Expression builder -Expressions are usually built using an instance of [ExpressionBuilder](https://kysely-org.github.io/kysely/classes/ExpressionBuilder.html). `DB` is the same database type you give to `Kysely` when you create an instance. `TB` is the union of all table names that are visible in the context. For example `ExpressionBuilder` means you can access `person` and `pet` tables and all their columns in the expression. +Expressions are usually built using an instance of [ExpressionBuilder](https://kysely-org.github.io/kysely-apidoc/interfaces/ExpressionBuilder.html). `DB` is the same database type you give to `Kysely` when you create an instance. `TB` is the union of all table names that are visible in the context. For example `ExpressionBuilder` means you can access `person` and `pet` tables and all their columns in the expression. You can get an instance of the expression builder by using a callback: @@ -27,14 +27,14 @@ const person = await db .limit(1) .as('pet_name'), - // Select a boolean expression. `cmpr` stands for `compare`. - eb.cmpr('first_name', '=', 'Jennifer').as('is_jennifer') + // Select a boolean expression.. + eb('first_name', '=', 'Jennifer').as('is_jennifer') ]) // You can also destructure the expression builder like this - .where(({ and, or, cmpr, not, exists, selectFrom }) => or([ + .where(({ and, or, eb, not, exists, selectFrom }) => or([ and([ - cmpr('first_name', '=', firstName), - cmpr('last_name', '=', lastName) + eb('first_name', '=', firstName), + eb('last_name', '=', lastName) ]), not(exists( selectFrom('pet') @@ -202,18 +202,18 @@ The same query can be built using the expression builder like this: const persons = await db .selectFrom('person') .selectAll('person') - .where(({ cmpr, and }) => { + .where((eb) => { const filters: Expression[] = [] if (firstName) { - filters.push(cmpr('first_name', '=', firstName)) + filters.push(eb('first_name', '=', firstName)) } if (lastName) { - filters.push(cmpr('last_name', '=', lastName)) + filters.push(eb('last_name', '=', lastName)) } - return and(filters) + return eb.and(filters) }) ``` diff --git a/site/docs/recipes/schemas.md b/site/docs/recipes/0007-schemas.md similarity index 96% rename from site/docs/recipes/schemas.md rename to site/docs/recipes/0007-schemas.md index 6b05d9cfb..0d8d2b94b 100644 --- a/site/docs/recipes/schemas.md +++ b/site/docs/recipes/0007-schemas.md @@ -43,7 +43,7 @@ db.selectFrom('user.user') In the multitenant case you have a schema per tenant and you can't add each of them to the database interface, nor would it make sense to do so. In this case you can use the -[withSchema](https://kysely-org.github.io/kysely/classes/Kysely.html#withSchema) method. +[withSchema](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#withSchema) method. The `withSchema` method sets the default schema of all table references that don't explicitly specify a schema: diff --git a/site/docs/recipes/deduplicate-joins.md b/site/docs/recipes/0008-deduplicate-joins.md similarity index 93% rename from site/docs/recipes/deduplicate-joins.md rename to site/docs/recipes/0008-deduplicate-joins.md index e1ba24830..2544fab08 100644 --- a/site/docs/recipes/deduplicate-joins.md +++ b/site/docs/recipes/0008-deduplicate-joins.md @@ -35,7 +35,7 @@ But if both `withPetName` and `withPetSpecies` are `true`, we end up with two id joins which will cause an error in the database. To prevent the error from happening, you can install the -[DeduplicateJoinsPlugin](https://kysely-org.github.io/kysely/classes/DeduplicateJoinsPlugin.html). +[DeduplicateJoinsPlugin](https://kysely-org.github.io/kysely-apidoc/classes/DeduplicateJoinsPlugin.html). You can either install it globally by providing it in the configuration: ```ts @@ -79,4 +79,4 @@ corner cases where the `DeduplicateJoinsPlugin` fails and we don't want it to af don't need this deduplication (most people). See [this recipe](/docs/recipes/conditional-selects) -if you are wondering why we are using the `if` method. +if you are wondering why we are using the `$if` method. diff --git a/site/docs/recipes/excessively-deep-types.md b/site/docs/recipes/0009-excessively-deep-types.md similarity index 75% rename from site/docs/recipes/excessively-deep-types.md rename to site/docs/recipes/0009-excessively-deep-types.md index db2053655..8a0862395 100644 --- a/site/docs/recipes/excessively-deep-types.md +++ b/site/docs/recipes/0009-excessively-deep-types.md @@ -7,13 +7,13 @@ 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 the [$assertType](https://kysely-org.github.io/kysely/classes/SelectQueryBuilder.html#_assertType) +In these case you can often use the [$assertType](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#_assertType) 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. -For example having more than 8 `with` statements in a query can lead to the `TS2589` error: +For example having more than 12 `with` statements in a query can lead to the `TS2589` error: ```ts const res = await db @@ -26,7 +26,11 @@ const res = await db .with('w7', (qb) => qb.selectFrom('person').select('first_name as fn7')) .with('w8', (qb) => qb.selectFrom('person').select('first_name as fn8')) .with('w9', (qb) => qb.selectFrom('person').select('first_name as fn9')) - .selectFrom(['w1', 'w2', 'w3', 'w4', 'w5', 'w6', 'w7', 'w8', 'w9']) + .with('w10', (qb) => qb.selectFrom('person').select('first_name as fn10')) + .with('w11', (qb) => qb.selectFrom('person').select('first_name as fn11')) + .with('w12', (qb) => qb.selectFrom('person').select('first_name as fn12')) + .with('w13', (qb) => qb.selectFrom('person').select('first_name as fn13')) + .selectFrom(['w1', 'w2', 'w3', 'w4', 'w5', 'w6', 'w7', 'w8', 'w9', 'w10', 'w11', 'w12', 'w13']) .selectAll() .executeTakeFirstOrThrow() ``` @@ -42,19 +46,23 @@ const res = await db .with('w5', (qb) => qb.selectFrom('person').select('first_name as fn5')) .with('w6', (qb) => qb.selectFrom('person').select('first_name as fn6')) .with('w7', (qb) => qb.selectFrom('person').select('first_name as fn7')) - .with('w8', (qb) => + .with('w8', (qb) => qb.selectFrom('person').select('first_name as fn8')) + .with('w9', (qb) => qb.selectFrom('person').select('first_name as fn9')) + .with('w10', (qb) => qb.selectFrom('person').select('first_name as fn10')) + .with('w11', (qb) => qb.selectFrom('person').select('first_name as fn11')) + .with('w12', (qb) => qb .selectFrom('person') - .select('first_name as fn8') - .$assertType<{ fn8: string }>() + .select('first_name as fn12') + .$assertType<{ fn12: string }>() ) - .with('w9', (qb) => + .with('w13', (qb) => qb .selectFrom('person') - .select('first_name as fn9') - .$assertType<{ fn9: string }>() + .select('first_name as fn13') + .$assertType<{ fn13: string }>() ) - .selectFrom(['w1', 'w2', 'w3', 'w4', 'w5', 'w6', 'w7', 'w8', 'w9']) + .selectFrom(['w1', 'w2', 'w3', 'w4', 'w5', 'w6', 'w7', 'w8', 'w9', 'w10', 'w11', 'w12', 'w13']) .selectAll() .executeTakeFirstOrThrow() ``` diff --git a/site/docs/recipes/extending-kysely.md b/site/docs/recipes/0010-extending-kysely.md similarity index 95% rename from site/docs/recipes/extending-kysely.md rename to site/docs/recipes/0010-extending-kysely.md index 667336b6a..6b42b147c 100644 --- a/site/docs/recipes/extending-kysely.md +++ b/site/docs/recipes/0010-extending-kysely.md @@ -5,18 +5,18 @@ that feature in a generic way that would work in all use cases would be really d In many cases it's better to create little helper functions in your project that suit your use case. Kysely makes this really simple. -The Kysely API is designed around two interfaces [`Expression`](https://kysely-org.github.io/kysely/interfaces/Expression.html) -and [`AliasedExpression`](https://kysely-org.github.io/kysely/interfaces/AliasedExpression.html). +The Kysely API is designed around two interfaces [`Expression`](https://kysely-org.github.io/kysely-apidoc/interfaces/Expression.html) +and [`AliasedExpression`](https://kysely-org.github.io/kysely-apidoc/interfaces/AliasedExpression.html). Almost every method accepts values that implement these interfaces and most Kysely internals achieve their "type magic" by implementing them. -Most of the time you can create your helpers using the [sql template tag](https://kysely-org.github.io/kysely/interfaces/Sql.html) +Most of the time you can create your helpers using the [sql template tag](https://kysely-org.github.io/kysely-apidoc/interfaces/Sql.html) and the `RawBuilder` and `AliasedRawBuilder` class instances it returns, but it's good to first understand how the underlying interfaces they implement, `Expression` and `AliasedExpression`, work. ## Expression -[`Expression`](https://kysely-org.github.io/kysely/interfaces/Expression.html) is a simple interface +[`Expression`](https://kysely-org.github.io/kysely-apidoc/interfaces/Expression.html) is a simple interface that has a type `T` and a single method `toOperationNode()`. `T` tells Kysely's type system the type of the expression. `toOperationNode()` returns instructions on what SQL should be produced once the expression is compiled. @@ -84,7 +84,7 @@ async function test(db: Kysely) { ``` Most of the time you don't need to create your own classes that implement the `Expression` interface. -You can simply wrap the [sql template tag](https://kysely-org.github.io/kysely/interfaces/Sql.html) and +You can simply wrap the [sql template tag](https://kysely-org.github.io/kysely-apidoc/interfaces/Sql.html) and the `RawBuilder` class instance it returns in a function. `RawBuilder`, like most things in Kysely, implements the `Expression` interface. @@ -136,7 +136,7 @@ async function test(db: Kysely) { ## AliasedExpression While `Expression` holds the type and compilation instructions of an SQL expression, -[`AliasedExpression`](https://kysely-org.github.io/kysely/interfaces/AliasedExpression.html) +[`AliasedExpression`](https://kysely-org.github.io/kysely-apidoc/interfaces/AliasedExpression.html) also holds an alias (a name) for that expression. `AliasedExpression` can be used in places where you need a name for the expression, like in a `SELECT` statement or a `FROM` statement. `AliasedExpression` is how kysely is able to infer the name and type of result columns. @@ -302,7 +302,7 @@ function values, A extends string>( ``` There's a lot going on in this function, but it's all documented in the -[sql template tag's documentation.](https://kysely-org.github.io/kysely/interfaces/Sql.html) +[sql template tag's documentation.](https://kysely-org.github.io/kysely-apidoc/interfaces/Sql.html) Most of the time a helper like this would return either an instance of `RawBuilder` or `AliasedRawBuilder` and you'd create an instance using the `sql` template tag. You'd return a diff --git a/site/docs/recipes/introspecting-relation-metadata.md b/site/docs/recipes/0011-introspecting-relation-metadata.md similarity index 69% rename from site/docs/recipes/introspecting-relation-metadata.md rename to site/docs/recipes/0011-introspecting-relation-metadata.md index e91577129..72101ba86 100644 --- a/site/docs/recipes/introspecting-relation-metadata.md +++ b/site/docs/recipes/0011-introspecting-relation-metadata.md @@ -6,7 +6,8 @@ The example below uses a PostgreSQL connection to print information about all ta ```ts import { Kysely, PostgresDialect } from 'kysely' -import { Pool } from 'pg' +import pg from 'pg' +const { Pool } = pg async function logDatabaseSchema() { const db = new Kysely({ @@ -17,11 +18,13 @@ async function logDatabaseSchema() { }), }) - const tables = await db().introspection.getTables() + const tables = await db.introspection.getTables() // ^? TableMetadata[] console.log({ tables }) } + +logDatabaseSchema() ``` -For more information check the docs for details on the interfaces [DatabaseIntrospector](https://kysely-org.github.io/kysely/interfaces/DatabaseIntrospector.html) and [TableMetadata](https://kysely-org.github.io/kysely/interfaces/TableMetadata.html). +For more information check the docs for details on the interfaces [DatabaseIntrospector](https://kysely-org.github.io/kysely-apidoc/interfaces/DatabaseIntrospector.html) and [TableMetadata](https://kysely-org.github.io/kysely-apidoc/interfaces/TableMetadata.html). diff --git a/site/docusaurus.config.js b/site/docusaurus.config.js index 44a75edd4..d69f89d47 100644 --- a/site/docusaurus.config.js +++ b/site/docusaurus.config.js @@ -86,6 +86,8 @@ const config = { logo: { alt: 'Kysely Logo', src: 'img/logo.svg', + width: 32, + height: 32, }, items: [ { @@ -101,7 +103,7 @@ const config = { position: 'right', }, { - href: 'https://kysely-org.github.io/kysely/', + href: 'https://kysely-org.github.io/kysely-apidoc/', label: 'API docs', position: 'right', }, @@ -170,7 +172,7 @@ const config = { }, { label: 'API docs', - href: 'https://kysely-org.github.io/kysely/', + href: 'https://kysely-org.github.io/kysely-apidoc/', }, ], }, @@ -178,7 +180,7 @@ const config = { title: 'Sponsors', items: [ { - html: `Powered by Vercel`, + html: `Powered by Vercel`, }, ], }, diff --git a/site/package-lock.json b/site/package-lock.json index bba654d7b..3bf9ab01c 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -1,6 +1,6 @@ { "name": "kysely", - "version": "0.25.0", + "version": "0.27.0", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/site/package.json b/site/package.json index ccf279b82..e7a00b440 100644 --- a/site/package.json +++ b/site/package.json @@ -1,6 +1,6 @@ { "name": "kysely", - "version": "0.25.0", + "version": "0.27.0", "private": true, "scripts": { "docusaurus": "docusaurus", diff --git a/site/src/components/DemoVideo.module.css b/site/src/components/DemoVideo.module.css new file mode 100644 index 000000000..cf46247b8 --- /dev/null +++ b/site/src/components/DemoVideo.module.css @@ -0,0 +1,21 @@ +.videoContainer { + width: 100%; + max-width: 832px; + height: 0; + padding-bottom: 55.59%; + position: relative; + overflow: hidden; +} + +.videoContainer video { + position: absolute; + top: 0; + width: fit-content; + height: 100%; + background: #1d1d1d; + left: 50%; + transform: translateX(-50%); + max-height: 610px; + border-radius: 12px; + box-shadow: var(--shadow-elevation-medium); +} diff --git a/site/src/components/DemoVideo.tsx b/site/src/components/DemoVideo.tsx new file mode 100644 index 000000000..d59782dd7 --- /dev/null +++ b/site/src/components/DemoVideo.tsx @@ -0,0 +1,12 @@ +import React from 'react' +import styles from './DemoVideo.module.css' + +export function DemoVideo() { + return ( +

+ +
+ ) +} diff --git a/site/src/pages/index.tsx b/site/src/pages/index.tsx index aa2557b91..466efc0a1 100644 --- a/site/src/pages/index.tsx +++ b/site/src/pages/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { ReactElement } from 'react' import clsx from 'clsx' import useDocusaurusContext from '@docusaurus/useDocusaurusContext' import Layout from '@theme/Layout' @@ -7,6 +7,7 @@ import D1Logo from '../../static/img/d1.svg' import styles from './index.module.css' import { gray } from '@radix-ui/colors' +import { DemoVideo } from '../components/DemoVideo' function HomepageHeader() { const { siteConfig } = useDocusaurusContext() @@ -54,15 +55,8 @@ function HomepageHeader() { -
- -
+ + - + @@ -137,22 +131,31 @@ export default function Home(): JSX.Element { ) } -function TweetQuote({ +const domainNameToIcon: Record = { + twitter: , + discord: , + github: , +} + +function Quote({ avatar, authorName, authorTitle, - tweetLink, + link, text, }: { avatar: string - tweetLink: string + link: string authorName: string authorTitle: string text: string }) { + const [, domainName] = link.toLowerCase().match(/https?:\/\/(?:www\.)?(.+)\./) + return ( - + {domainNameToIcon[domainName] || null}
- + {`${authorName}'s
- - - - - + + - + + - + + + + + + - - - - + + -Knew nothing about the adapter and Kysely before and got the PoC in Code in 45 minutes. -It's so stupidly simple! [...] -`} + - + + -
@@ -392,6 +439,57 @@ function TwitterIcon() { ) } +function DiscordIcon() { + return ( + + ) +} + +function GithubIcon() { + return ( + + ) +} + function SectionPlayground() { return (
diff --git a/site/static/demo.mp4 b/site/static/demo.mp4 new file mode 100644 index 000000000..0c506e2df Binary files /dev/null and b/site/static/demo.mp4 differ diff --git a/site/static/img/avatars/alberto.jpeg b/site/static/img/avatars/alberto.jpeg new file mode 100644 index 000000000..e23e8c329 Binary files /dev/null and b/site/static/img/avatars/alberto.jpeg differ diff --git a/site/static/img/avatars/alexanderson.jpeg b/site/static/img/avatars/alexanderson.jpeg new file mode 100644 index 000000000..046db7427 Binary files /dev/null and b/site/static/img/avatars/alexanderson.jpeg differ diff --git a/site/static/img/avatars/benholmes.jpeg b/site/static/img/avatars/benholmes.jpeg new file mode 100644 index 000000000..8783f82ee Binary files /dev/null and b/site/static/img/avatars/benholmes.jpeg differ diff --git a/site/static/img/avatars/daxraad.jpeg b/site/static/img/avatars/daxraad.jpeg new file mode 100644 index 000000000..eb705a3ff Binary files /dev/null and b/site/static/img/avatars/daxraad.jpeg differ diff --git a/site/static/img/avatars/gal.jpeg b/site/static/img/avatars/gal.jpeg new file mode 100644 index 000000000..1ed815653 Binary files /dev/null and b/site/static/img/avatars/gal.jpeg differ diff --git a/site/static/img/avatars/gannon.jpeg b/site/static/img/avatars/gannon.jpeg new file mode 100644 index 000000000..80d96d2cc Binary files /dev/null and b/site/static/img/avatars/gannon.jpeg differ diff --git a/site/static/img/avatars/harminder.jpeg b/site/static/img/avatars/harminder.jpeg new file mode 100644 index 000000000..f61989b7b Binary files /dev/null and b/site/static/img/avatars/harminder.jpeg differ diff --git a/site/static/img/avatars/johan.jpeg b/site/static/img/avatars/johan.jpeg new file mode 100644 index 000000000..a2f1e5d85 Binary files /dev/null and b/site/static/img/avatars/johan.jpeg differ diff --git a/site/static/img/avatars/julius.jpeg b/site/static/img/avatars/julius.jpeg new file mode 100644 index 000000000..5bbe0d9f4 Binary files /dev/null and b/site/static/img/avatars/julius.jpeg differ diff --git a/site/static/img/avatars/leerob.jpeg b/site/static/img/avatars/leerob.jpeg new file mode 100644 index 000000000..0d5627768 Binary files /dev/null and b/site/static/img/avatars/leerob.jpeg differ diff --git a/site/static/img/avatars/mehul.jpeg b/site/static/img/avatars/mehul.jpeg new file mode 100644 index 000000000..5e76f2238 Binary files /dev/null and b/site/static/img/avatars/mehul.jpeg differ diff --git a/site/static/img/avatars/nexxel.jpeg b/site/static/img/avatars/nexxel.jpeg new file mode 100644 index 000000000..a699e4f72 Binary files /dev/null and b/site/static/img/avatars/nexxel.jpeg differ diff --git a/site/static/img/avatars/nicholas.jpeg b/site/static/img/avatars/nicholas.jpeg new file mode 100644 index 000000000..d13f703ca Binary files /dev/null and b/site/static/img/avatars/nicholas.jpeg differ diff --git a/site/static/img/avatars/orta.jpeg b/site/static/img/avatars/orta.jpeg new file mode 100644 index 000000000..b736b0f42 Binary files /dev/null and b/site/static/img/avatars/orta.jpeg differ diff --git a/site/static/img/avatars/pilcrowonpaper.jpeg b/site/static/img/avatars/pilcrowonpaper.jpeg new file mode 100644 index 000000000..10013d7e6 Binary files /dev/null and b/site/static/img/avatars/pilcrowonpaper.jpeg differ diff --git a/site/static/img/avatars/ross.jpeg b/site/static/img/avatars/ross.jpeg new file mode 100644 index 000000000..6807cdff6 Binary files /dev/null and b/site/static/img/avatars/ross.jpeg differ diff --git a/site/static/img/avatars/samcook.jpeg b/site/static/img/avatars/samcook.jpeg new file mode 100644 index 000000000..f4526775b Binary files /dev/null and b/site/static/img/avatars/samcook.jpeg differ diff --git a/site/static/img/avatars/sommelier.jpeg b/site/static/img/avatars/sommelier.jpeg new file mode 100644 index 000000000..debd528a3 Binary files /dev/null and b/site/static/img/avatars/sommelier.jpeg differ diff --git a/site/static/img/avatars/tgriesser.jpeg b/site/static/img/avatars/tgriesser.jpeg new file mode 100644 index 000000000..ef59cbe61 Binary files /dev/null and b/site/static/img/avatars/tgriesser.jpeg differ diff --git a/site/static/img/avatars/theo.jpeg b/site/static/img/avatars/theo.jpeg new file mode 100644 index 000000000..12f280139 Binary files /dev/null and b/site/static/img/avatars/theo.jpeg differ diff --git a/site/static/img/avatars/yusuke.jpeg b/site/static/img/avatars/yusuke.jpeg new file mode 100644 index 000000000..4fd2b6101 Binary files /dev/null and b/site/static/img/avatars/yusuke.jpeg differ diff --git a/src/dialect/database-introspector.ts b/src/dialect/database-introspector.ts index 608b3f230..75093b811 100644 --- a/src/dialect/database-introspector.ts +++ b/src/dialect/database-introspector.ts @@ -35,7 +35,7 @@ export interface SchemaMetadata { export interface DatabaseMetadata { /** * The tables and views found in the database. -* * The propery isView can be used to tell them apart. + * The propery isView can be used to tell them apart. */ readonly tables: TableMetadata[] } @@ -68,4 +68,5 @@ export interface ColumnMetadata { readonly isAutoIncrementing: boolean readonly isNullable: boolean readonly hasDefaultValue: boolean + readonly comment?: string } diff --git a/src/dialect/dialect-adapter-base.ts b/src/dialect/dialect-adapter-base.ts index 028adf26a..7910bf394 100644 --- a/src/dialect/dialect-adapter-base.ts +++ b/src/dialect/dialect-adapter-base.ts @@ -1,5 +1,5 @@ import { Kysely } from '../kysely.js' -import { DialectAdapter } from './dialect-adapter.js' +import { DialectAdapter, MigrationLockOptions } from './dialect-adapter.js' /** * A basic implementation of `DialectAdapter` with sensible default values. @@ -8,6 +8,10 @@ import { DialectAdapter } from './dialect-adapter.js' * they are added and there will be less breaking changes. */ export abstract class DialectAdapterBase implements DialectAdapter { + get supportsCreateIfNotExists(): boolean { + return true + } + get supportsTransactionalDdl(): boolean { return false } @@ -16,6 +20,17 @@ export abstract class DialectAdapterBase implements DialectAdapter { return false } - abstract acquireMigrationLock(db: Kysely): Promise - abstract releaseMigrationLock(db: Kysely): Promise + get supportsOutput(): boolean { + return false + } + + abstract acquireMigrationLock( + db: Kysely, + options: MigrationLockOptions, + ): Promise + + abstract releaseMigrationLock( + db: Kysely, + options: MigrationLockOptions, + ): Promise } diff --git a/src/dialect/dialect-adapter.ts b/src/dialect/dialect-adapter.ts index 2aede8b1f..d4020278b 100644 --- a/src/dialect/dialect-adapter.ts +++ b/src/dialect/dialect-adapter.ts @@ -9,6 +9,15 @@ import { Kysely } from '../kysely.js' * it. For that there's a `supportsTransactionalDdl` boolean in this interface. */ export interface DialectAdapter { + /** + * Whether or not this dialect supports `if not exists` in creation of tables/schemas/views/etc. + * + * If this is false, Kysely's internal migrations tables and schemas are created + * without `if not exists` in migrations. This is not a problem if the dialect + * supports transactional DDL. + */ + readonly supportsCreateIfNotExists: boolean + /** * Whether or not this dialect supports transactional DDL. * @@ -22,6 +31,12 @@ export interface DialectAdapter { */ readonly supportsReturning: boolean + /** + * Whether or not this dialect supports the `output` clause in inserts + * updates and deletes. + */ + readonly supportsOutput?: boolean + /** * This method is used to acquire a lock for the migrations so that * it's not possible for two migration operations to run in parallel. @@ -69,7 +84,7 @@ export interface DialectAdapter { */ acquireMigrationLock( db: Kysely, - options: MigrationLockOptions + options: MigrationLockOptions, ): Promise /** @@ -82,7 +97,7 @@ export interface DialectAdapter { */ releaseMigrationLock( db: Kysely, - options: MigrationLockOptions + options: MigrationLockOptions, ): Promise } diff --git a/src/dialect/mssql/mssql-adapter.ts b/src/dialect/mssql/mssql-adapter.ts new file mode 100644 index 000000000..721178907 --- /dev/null +++ b/src/dialect/mssql/mssql-adapter.ts @@ -0,0 +1,34 @@ +import { Kysely } from '../../kysely.js' +import { DEFAULT_MIGRATION_TABLE } from '../../migration/migrator.js' +import { sql } from '../../raw-builder/sql.js' +import { DialectAdapterBase } from '../dialect-adapter-base.js' + +export class MssqlAdapter extends DialectAdapterBase { + get supportsCreateIfNotExists(): boolean { + return false + } + + get supportsTransactionalDdl(): boolean { + return true + } + + get supportsOutput(): boolean { + return true + } + + async acquireMigrationLock(db: Kysely): Promise { + // Acquire a transaction-level exclusive lock on the migrations table. + // https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-getapplock-transact-sql?view=sql-server-ver16 + await sql`exec sp_getapplock @DbPrincipal = ${sql.lit( + 'dbo', + )}, @Resource = ${sql.lit(DEFAULT_MIGRATION_TABLE)}, @LockMode = ${sql.lit( + 'Exclusive', + )}`.execute(db) + } + + async releaseMigrationLock(): Promise { + // Nothing to do here. `sp_getapplock` is automatically released at the + // end of the transaction and since `supportsTransactionalDdl` true, we know + // the `db` instance passed to acquireMigrationLock is actually a transaction. + } +} diff --git a/src/dialect/mssql/mssql-dialect-config.ts b/src/dialect/mssql/mssql-dialect-config.ts new file mode 100644 index 000000000..f82abe9f5 --- /dev/null +++ b/src/dialect/mssql/mssql-dialect-config.ts @@ -0,0 +1,208 @@ +export interface MssqlDialectConfig { + /** + * This dialect uses the `tarn` package to manage the connection pool to your + * database. To use it as a peer dependency and not bundle it with Kysely's code, + * you need to pass the `tarn` package itself. You also need to pass some pool options + * (excluding `create`, `destroy` and `validate` functions which are controlled by this dialect), + * `min` & `max` connections at the very least. + * + * Example: + * + * ```ts + * import * as Tarn from 'tarn' + * + * const dialect = new MssqlDialect({ + * // ... + * tarn: { + * ...Tarn, + * options: { + * // ... + * min: 0, + * max: 10, + * }, + * }, + * }) + * ``` + */ + tarn: Tarn + + /** + * This dialect uses the `tedious` package to communicate with your MS SQL Server + * database. To use it as a peer dependency and not bundle it with Kysely's code, + * you need to pass the `tedious` package itself. You also need to pass a factory + * function that creates new `tedious` `Connection` instances on demand. + * + * Example: + * + * ```ts + * import * as Tedious from 'tedious' + * + * const dialect = new MssqlDialect({ + * // ... + * tedious: { + * ...Tedious, + * connectionFactory: () => new Tedious.Connection({ ... }), + * }, + * }) + * ``` + */ + tedious: Tedious +} + +export interface Tedious { + connectionFactory: () => TediousConnection | Promise + ISOLATION_LEVEL: TediousIsolationLevel + Request: typeof TediousRequest + TYPES: TediousTypes +} + +export type TediousIsolationLevel = Record< + | 'NO_CHANGE' + | 'READ_UNCOMMITTED' + | 'READ_COMMITTED' + | 'REPEATABLE_READ' + | 'SERIALIZABLE' + | 'SNAPSHOT', + number +> + +export type TediousTypes = Record< + | 'BigInt' + | 'Binary' + | 'Bit' + | 'Char' + | 'Date' + | 'DateTime' + | 'DateTime2' + | 'DateTimeOffset' + | 'Decimal' + | 'Float' + | 'Image' + | 'Int' + | 'Money' + | 'NChar' + | 'NText' + | 'Null' + | 'Numeric' + | 'NVarChar' + | 'Real' + | 'SmallDateTime' + | 'SmallInt' + | 'SmallMoney' + | 'Text' + | 'Time' + | 'TinyInt' + | 'TVP' + | 'UDT' + | 'UniqueIdentifier' + | 'VarBinary' + | 'VarChar' + // TODO: uncomment once it is introduced in @types/tedious. See https://github.com/DefinitelyTyped/DefinitelyTyped/pull/66369 + // | 'Variant' + | 'Xml', + { name: string; type: string } +> + +export interface TediousType { + name: string + type: string +} + +export interface TediousConnection { + beginTransaction( + callback: (error?: Error) => void, + transactionId?: string | undefined, + isolationLevel?: number | undefined, + ): void + cancel(): void + close(): void + commitTransaction(callback: (error?: Error) => void): void + connect(callback: (error?: Error) => void): void + execSql(request: TediousRequest): void + reset(callback: (error?: Error) => void): void + rollbackTransaction(callback: (error?: Error) => void): void + once(event: 'end', listener: () => void): void +} + +export declare class TediousRequest { + constructor( + sql: string, + callback: (error: Error, rowCount: number, rows: any[]) => void, + ) + addParameter( + name: string, + type: TediousType, + value: any, + options?: { + length?: number | 'max' | undefined + precision?: number | undefined + scale?: number | undefined + }, + ): void + off(event: 'row', listener: (...args: any[]) => void): void + on(event: 'row', listener: (columns: TediousColumnValue[]) => void): void + once(event: 'requestCompleted', listener: (...args: any[]) => void): void +} + +export interface TediousColumnValue { + metadata: { + colName: string + } + value: any +} + +export interface Tarn { + /** + * Tarn.js' pool options, excluding `create`, `destroy` and `validate` functions, + * which must be implemented by this dialect. + */ + options: Omit, 'create' | 'destroy' | 'validate'> + + /** + * Tarn.js' Pool class. + * + * Example: + * + * ```ts + * import { Pool } from 'tarn' + * + * const dialect = new MssqlDialect({ + * // ... + * tarn: { + * // ... + * Pool, + * }, + * }) + * ``` + */ + Pool: typeof TarnPool +} + +export declare class TarnPool { + constructor(opt: TarnPoolOptions) + acquire(): TarnPendingRequest + destroy(): any + release(resource: R): void +} + +export interface TarnPoolOptions { + acquireTimeoutMillis?: number + create(cb: (err: Error | null, resource: R) => void): any | (() => Promise) + createRetryIntervalMillis?: number + createTimeoutMillis?: number + destroy(resource: R): any + destroyTimeoutMillis?: number + idleTimeoutMillis?: number + log?(msg: string): any + max: number + min: number + propagateCreateError?: boolean + reapIntervalMillis?: number + validate(resource: R): boolean +} + +export interface TarnPendingRequest { + promise: Promise + resolve: (resource: R) => void + reject: (err: Error) => void +} diff --git a/src/dialect/mssql/mssql-dialect.ts b/src/dialect/mssql/mssql-dialect.ts new file mode 100644 index 000000000..f9ea61ad1 --- /dev/null +++ b/src/dialect/mssql/mssql-dialect.ts @@ -0,0 +1,74 @@ +import { Driver } from '../../driver/driver.js' +import { Kysely } from '../../kysely.js' +import { QueryCompiler } from '../../query-compiler/query-compiler.js' +import { DatabaseIntrospector } from '../database-introspector.js' +import { DialectAdapter } from '../dialect-adapter.js' +import { Dialect } from '../dialect.js' +import { MssqlAdapter } from './mssql-adapter.js' +import { MssqlDialectConfig } from './mssql-dialect-config.js' +import { MssqlDriver } from './mssql-driver.js' +import { MssqlIntrospector } from './mssql-introspector.js' +import { MssqlQueryCompiler } from './mssql-query-compiler.js' + +/** + * MS SQL Server dialect that uses the [tedious](https://tediousjs.github.io/tedious) + * library. + * + * The constructor takes an instance of {@link MssqlDialectConfig}. + * + * ```ts + * import * as Tedious from 'tedious' + * import * as Tarn from 'tarn' + * + * const dialect = new MssqlDialect({ + * tarn: { + * ...Tarn, + * options: { + * min: 0, + * max: 10, + * }, + * }, + * tedious: { + * ...Tedious, + * connectionFactory: () => new Tedious.Connection({ + * authentication: { + * options: { + * password: 'password', + * userName: 'username', + * }, + * type: 'default', + * }, + * options: { + * database: 'some_db', + * port: 1433, + * trustServerCertificate: true, + * }, + * server: 'localhost', + * }), + * }, + * }) + * ``` + */ +export class MssqlDialect implements Dialect { + readonly #config: MssqlDialectConfig + + constructor(config: MssqlDialectConfig) { + this.#config = config + } + + createDriver(): Driver { + return new MssqlDriver(this.#config) + } + + createQueryCompiler(): QueryCompiler { + return new MssqlQueryCompiler() + } + + createAdapter(): DialectAdapter { + return new MssqlAdapter() + } + + createIntrospector(db: Kysely): DatabaseIntrospector { + return new MssqlIntrospector(db) + } +} diff --git a/src/dialect/mssql/mssql-driver.ts b/src/dialect/mssql/mssql-driver.ts new file mode 100644 index 000000000..5d9b9cb12 --- /dev/null +++ b/src/dialect/mssql/mssql-driver.ts @@ -0,0 +1,390 @@ +import { + DatabaseConnection, + QueryResult, +} from '../../driver/database-connection.js' +import { + Driver, + IsolationLevel, + TransactionSettings, +} from '../../driver/driver.js' +import { + freeze, + isBigInt, + isBoolean, + isBuffer, + isDate, + isNull, + isNumber, + isString, + isUndefined, +} from '../../util/object-utils.js' +import { + MssqlDialectConfig, + TarnPool, + Tedious, + TediousColumnValue, + TediousConnection, + TediousRequest, +} from './mssql-dialect-config.js' +import { CompiledQuery } from '../../query-compiler/compiled-query.js' +import { extendStackTrace } from '../../util/stack-trace-utils.js' +import { randomString } from '../../util/random-string.js' +import { Deferred } from '../../util/deferred.js' + +const PRIVATE_RELEASE_METHOD = Symbol() +const PRIVATE_DESTROY_METHOD = Symbol() + +export class MssqlDriver implements Driver { + readonly #config: MssqlDialectConfig + readonly #pool: TarnPool + + constructor(config: MssqlDialectConfig) { + this.#config = freeze({ ...config }) + + this.#pool = new this.#config.tarn.Pool({ + ...this.#config.tarn.options, + create: async () => { + const connection = await this.#config.tedious.connectionFactory() + + await new Promise((resolve, reject) => + connection.connect((error) => { + if (error) reject(error) + else resolve(undefined) + }), + ) + + return new MssqlConnection(connection, this.#config.tedious) + }, + destroy: async (connection) => { + await connection[PRIVATE_DESTROY_METHOD]() + }, + // @ts-ignore `tarn` accepts a function that returns a promise here, but + // the types are not aligned and it type errors. + validate: (connection) => connection.validate(), + }) + } + + async init(): Promise { + // noop + } + + async acquireConnection(): Promise { + return await this.#pool.acquire().promise + } + + async beginTransaction( + connection: MssqlConnection, + settings: TransactionSettings, + ): Promise { + await connection.beginTransaction(settings) + } + + async commitTransaction(connection: MssqlConnection): Promise { + await connection.commitTransaction() + } + + async rollbackTransaction(connection: MssqlConnection): Promise { + await connection.rollbackTransaction() + } + + async releaseConnection(connection: MssqlConnection): Promise { + await connection[PRIVATE_RELEASE_METHOD]() + this.#pool.release(connection) + } + + async destroy(): Promise { + await this.#pool.destroy() + } +} + +class MssqlConnection implements DatabaseConnection { + readonly #connection: TediousConnection + readonly #tedious: Tedious + + constructor(connection: TediousConnection, tedious: Tedious) { + this.#connection = connection + this.#tedious = tedious + } + + async beginTransaction(settings: TransactionSettings): Promise { + const { isolationLevel } = settings + + await new Promise((resolve, reject) => + this.#connection.beginTransaction( + (error) => { + if (error) reject(error) + else resolve(undefined) + }, + isolationLevel ? randomString(8) : undefined, + isolationLevel + ? this.#getTediousIsolationLevel(isolationLevel) + : undefined, + ), + ) + } + + async commitTransaction(): Promise { + await new Promise((resolve, reject) => + this.#connection.commitTransaction((error) => { + if (error) reject(error) + else resolve(undefined) + }), + ) + } + + async executeQuery(compiledQuery: CompiledQuery): Promise> { + try { + const deferred = new Deferred>() + + const request = new MssqlRequest( + this.#tedious, + compiledQuery, + deferred, + ) + + this.#connection.execSql(request.request) + + const { rowCount, rows } = await deferred.promise + + return { + numAffectedRows: rowCount !== undefined ? BigInt(rowCount) : undefined, + rows, + } + } catch (err) { + throw extendStackTrace(err, new Error()) + } + } + + async rollbackTransaction(): Promise { + await new Promise((resolve, reject) => + this.#connection.rollbackTransaction((error) => { + if (error) reject(error) + else resolve(undefined) + }), + ) + } + + async *streamQuery( + compiledQuery: CompiledQuery, + chunkSize: number, + ): AsyncIterableIterator> { + if (!Number.isInteger(chunkSize) || chunkSize <= 0) { + throw new Error('chunkSize must be a positive integer') + } + + const request = new MssqlRequest(this.#tedious, compiledQuery) + + this.#connection.execSql(request.request) + + try { + while (true) { + const rows = await request.readChunk(chunkSize) + + if (rows.length === 0) { + break + } + + yield { rows } + + if (rows.length < chunkSize) { + break + } + } + } finally { + this.#connection.cancel() + } + } + + async validate(): Promise { + try { + const deferred = new Deferred>() + + const request = new MssqlRequest( + this.#tedious, + CompiledQuery.raw('select 1'), + deferred, + ) + + this.#connection.execSql(request.request) + + await deferred.promise + + return true + } catch { + return false + } + } + + #getTediousIsolationLevel(isolationLevel: IsolationLevel) { + const { ISOLATION_LEVEL } = this.#tedious + + const mapper: Record< + IsolationLevel, + (typeof ISOLATION_LEVEL)[keyof typeof ISOLATION_LEVEL] + > = { + 'read committed': ISOLATION_LEVEL.READ_COMMITTED, + 'read uncommitted': ISOLATION_LEVEL.READ_UNCOMMITTED, + 'repeatable read': ISOLATION_LEVEL.REPEATABLE_READ, + serializable: ISOLATION_LEVEL.SERIALIZABLE, + snapshot: ISOLATION_LEVEL.SNAPSHOT, + } + + const tediousIsolationLevel = mapper[isolationLevel] + + if (tediousIsolationLevel === undefined) { + throw new Error(`Unknown isolation level: ${isolationLevel}`) + } + + return tediousIsolationLevel + } + + [PRIVATE_RELEASE_METHOD](): Promise { + return new Promise((resolve, reject) => { + this.#connection.reset((error) => { + if (error) reject(error) + else resolve(undefined) + }) + }) + } + + [PRIVATE_DESTROY_METHOD](): Promise { + return new Promise((resolve) => { + this.#connection.once('end', () => { + resolve(undefined) + }) + + this.#connection.close() + }) + } +} + +interface OnDone { + rowCount: number | undefined + rows: O[] +} + +interface PlainDeferred { + reject: (reason: any) => void + resolve: (value?: O) => void +} + +class MssqlRequest { + readonly #request: TediousRequest + readonly #rows: O[] + readonly #tedious: Tedious + #completed: boolean + #error: Error | any[] | undefined + #rowCount: number | undefined + + constructor( + tedious: Tedious, + compiledQuery: CompiledQuery, + onDone?: Deferred> | PlainDeferred>, + ) { + this.#completed = false + this.#rows = [] + this.#tedious = tedious + + const { parameters, sql } = compiledQuery + + this.#request = new this.#tedious.Request(sql, (err, rowCount) => { + if (err) { + this.#error = err instanceof AggregateError ? err.errors : err + onDone?.reject(this.#error) + } else { + this.#rowCount = rowCount + } + }) + + this.#addParametersToRequest(parameters) + this.#attachListeners(onDone) + } + + get request(): TediousRequest { + return this.#request + } + + readChunk(chunkSize: number): Promise { + return new Promise((resolve, reject) => { + const interval = setInterval(() => { + if (this.#error) { + clearInterval(interval) + reject(this.#error) + } else if (this.#completed || this.#rows.length >= chunkSize) { + clearInterval(interval) + resolve(this.#rows.splice(0, chunkSize)) + } + }, 0) + }) + } + + #addParametersToRequest(parameters: readonly unknown[]): void { + for (let i = 0; i < parameters.length; i++) { + const parameter = parameters[i] + + this.#request.addParameter( + String(i + 1), + this.#getTediousDataType(parameter), + parameter, + ) + } + } + + #attachListeners( + onDone: Deferred> | PlainDeferred> | undefined, + ): void { + const rowListener = (columns: TediousColumnValue[]) => { + const row: Record = {} + + for (const column of columns) { + row[column.metadata.colName] = column.value + } + + this.#rows.push(row as O) + } + + this.#request.on('row', rowListener) + + this.#request.once('requestCompleted', () => { + this.#completed = true + this.#request.off('row', rowListener) + + onDone?.resolve({ + rowCount: this.#rowCount, + rows: this.#rows, + }) + }) + } + + #getTediousDataType(value: unknown): any { + if (isNull(value) || isUndefined(value) || isString(value)) { + return this.#tedious.TYPES.NVarChar + } + + if (isBigInt(value) || (isNumber(value) && value % 1 === 0)) { + if (value < -2147483648 || value > 2147483647) { + return this.#tedious.TYPES.BigInt + } else { + return this.#tedious.TYPES.Int + } + } + + if (isNumber(value)) { + return this.#tedious.TYPES.Float + } + + if (isBoolean(value)) { + return this.#tedious.TYPES.Bit + } + + if (isDate(value)) { + return this.#tedious.TYPES.DateTime + } + + if (isBuffer(value)) { + return this.#tedious.TYPES.VarBinary + } + + return this.#tedious.TYPES.NVarChar + } +} diff --git a/src/dialect/mssql/mssql-introspector.ts b/src/dialect/mssql/mssql-introspector.ts new file mode 100644 index 000000000..9b2a9baf0 --- /dev/null +++ b/src/dialect/mssql/mssql-introspector.ts @@ -0,0 +1,326 @@ +import { Kysely } from '../../kysely.js' +import { + DatabaseIntrospector, + DatabaseMetadata, + DatabaseMetadataOptions, + SchemaMetadata, + TableMetadata, +} from '../database-introspector.js' +import { + DEFAULT_MIGRATION_LOCK_TABLE, + DEFAULT_MIGRATION_TABLE, +} from '../../migration/migrator.js' +import { freeze } from '../../util/object-utils.js' + +export class MssqlIntrospector implements DatabaseIntrospector { + readonly #db: Kysely + + constructor(db: Kysely) { + this.#db = db + } + + async getSchemas(): Promise { + return await this.#db.selectFrom('sys.schemas').select('name').execute() + } + + async getTables( + options: DatabaseMetadataOptions = { withInternalKyselyTables: false }, + ): Promise { + const rawColumns = await this.#db + .selectFrom('sys.tables as tables') + .leftJoin( + 'sys.schemas as table_schemas', + 'table_schemas.schema_id', + 'tables.schema_id', + ) + .innerJoin( + 'sys.columns as columns', + 'columns.object_id', + 'tables.object_id', + ) + .innerJoin( + 'sys.types as types', + 'types.user_type_id', + 'columns.user_type_id', + ) + .leftJoin( + 'sys.schemas as type_schemas', + 'type_schemas.schema_id', + 'types.schema_id', + ) + .leftJoin('sys.extended_properties as comments', (join) => + join + .onRef('comments.major_id', '=', 'tables.object_id') + .onRef('comments.minor_id', '=', 'columns.column_id') + .on('comments.name', '=', 'MS_Description'), + ) + .$if(!options.withInternalKyselyTables, (qb) => + qb + .where('tables.name', '!=', DEFAULT_MIGRATION_TABLE) + .where('tables.name', '!=', DEFAULT_MIGRATION_LOCK_TABLE), + ) + .select([ + 'tables.name as table_name', + (eb) => + eb + .ref('tables.type') + .$castTo< + | MssqlSysTables['sys.tables']['type'] + | MssqlSysTables['sys.views']['type'] + >() + .as('table_type'), + 'table_schemas.name as table_schema_name', + 'columns.default_object_id as column_default_object_id', + 'columns.generated_always_type_desc as column_generated_always_type', + 'columns.is_computed as column_is_computed', + 'columns.is_identity as column_is_identity', + 'columns.is_nullable as column_is_nullable', + 'columns.is_rowguidcol as column_is_rowguidcol', + 'columns.name as column_name', + 'types.is_nullable as type_is_nullable', + 'types.name as type_name', + 'type_schemas.name as type_schema_name', + 'comments.value as column_comment', + ]) + .unionAll( + this.#db + .selectFrom('sys.views as views') + .leftJoin( + 'sys.schemas as view_schemas', + 'view_schemas.schema_id', + 'views.schema_id', + ) + .innerJoin( + 'sys.columns as columns', + 'columns.object_id', + 'views.object_id', + ) + .innerJoin( + 'sys.types as types', + 'types.user_type_id', + 'columns.user_type_id', + ) + .leftJoin( + 'sys.schemas as type_schemas', + 'type_schemas.schema_id', + 'types.schema_id', + ) + .leftJoin('sys.extended_properties as comments', (join) => + join + .onRef('comments.major_id', '=', 'views.object_id') + .onRef('comments.minor_id', '=', 'columns.column_id') + .on('comments.name', '=', 'MS_Description'), + ) + .select([ + 'views.name as table_name', + 'views.type as table_type', + 'view_schemas.name as table_schema_name', + 'columns.default_object_id as column_default_object_id', + 'columns.generated_always_type_desc as column_generated_always_type', + 'columns.is_computed as column_is_computed', + 'columns.is_identity as column_is_identity', + 'columns.is_nullable as column_is_nullable', + 'columns.is_rowguidcol as column_is_rowguidcol', + 'columns.name as column_name', + 'types.is_nullable as type_is_nullable', + 'types.name as type_name', + 'type_schemas.name as type_schema_name', + 'comments.value as column_comment', + ]), + ) + .orderBy('table_schema_name') + .orderBy('table_name') + .orderBy('column_name') + .execute() + + const tableDictionary: Record = {} + + for (const rawColumn of rawColumns) { + const key = `${rawColumn.table_schema_name}.${rawColumn.table_name}` + + const table = (tableDictionary[key] = + tableDictionary[key] || + freeze({ + columns: [], + isView: rawColumn.table_type === 'V ', + name: rawColumn.table_name, + schema: rawColumn.table_schema_name ?? undefined, + })) + + table.columns.push( + freeze({ + dataType: rawColumn.type_name, + dataTypeSchema: rawColumn.type_schema_name ?? undefined, + hasDefaultValue: + rawColumn.column_default_object_id > 0 || + rawColumn.column_generated_always_type !== 'NOT_APPLICABLE' || + rawColumn.column_is_identity || + rawColumn.column_is_computed || + rawColumn.column_is_rowguidcol, + isAutoIncrementing: rawColumn.column_is_identity, + isNullable: + rawColumn.column_is_nullable && rawColumn.type_is_nullable, + name: rawColumn.column_name, + comment: rawColumn.column_comment ?? undefined, + }), + ) + } + + return Object.values(tableDictionary) + } + + async getMetadata( + options?: DatabaseMetadataOptions, + ): Promise { + return { + tables: await this.getTables(options), + } + } +} + +interface MssqlSysTables { + 'sys.columns': { + // collation_name: string | null + // column_encryption_key_database_name: null + // column_encryption_key_id: null + column_id: number + default_object_id: number + // encryption_algorithm_name: null + // encryption_type: null + // encryption_type_desc: null + // generated_always_type: number + generated_always_type_desc: string + // graph_type: number + // graph_type_desc: string + // is_ansi_padded: boolean + // is_column_set: boolean + is_computed: boolean + // is_data_deletion_filter_column: boolean + // is_dropped_ledger_column: boolean + // is_dts_replicated: boolean + // is_filestream: boolean + // is_hidden: boolean + is_identity: boolean + // is_masked: boolean + // is_merge_published: boolean + // is_non_sql_subscribed: boolean + is_nullable: boolean + // is_replicated: boolean + is_rowguidcol: boolean + // is_sparse: boolean + // is_xml_document: boolean + // ledger_view_column_type: null + // ledger_view_column_type_desc: null + // max_length: number + name: string + object_id: number + // precision: number + // rule_object_id: number + // scale: number + user_type_id: number + system_type_id: number + } + 'sys.extended_properties': { + major_id: number + minor_id: number + name: string + value: string + } + 'sys.schemas': { + name: string + // principal_id: number + schema_id: number + } + 'sys.tables': { + // create_date: Date + // data_retention_period: number + // data_retention_period_unit: number + // data_retention_period_unit_desc: string + // durability: number + // durability_desc: string + // filestream_data_space_id: number | null + // has_replication_filter: boolean + // has_unchecked_assembly_data: boolean + // history_retention_period: null + // history_retention_period_unit: null + // history_retention_period_unit_desc: null + // history_table_id: null + // is_dropped_ledger_table: boolean + // is_edge: boolean + // is_external: boolean + // is_filetable: boolean + // is_memory_optimized: boolean + // is_merge_published: boolean + // is_ms_shipped: boolean + // is_node: boolean + // is_published: boolean + // is_remote_data_archive_enabled: boolean + // is_replicated: boolean + // is_schema_published: boolean + // is_sync_tran_subscribed: boolean + // is_tracked_by_cdc: boolean + // large_value_types_out_of_row: boolean + // ledger_type: number + // ledger_type_desc: string + // ledger_view_id: null + // lob_data_space_id: number + // lock_escalation: number + // lock_escalation_desc: string + // lock_on_bulk_load: boolean + // max_column_id_used: number + // modify_date: Date + name: string + object_id: number + // parent_object_id: number + // principal_id: number | null + schema_id: number + // temporal_type: number + // temporal_type_desc: string + // text_in_row_limit: number + type: 'U ' + // type_desc: 'USER_TABLE' + // uses_ansi_nulls: boolean + } + 'sys.types': { + // collation_name: string | null + // default_object_id: number + // is_assembly_type: boolean + is_nullable: boolean + // is_table_type: boolean + // is_user_defined: boolean + // max_length: number + name: string + // precision: number + // principal_id: number | null + // rule_object_id: number + // scale: number + schema_id: number + system_type_id: number + user_type_id: number + } + 'sys.views': { + // create_date: Date + // has_opaque_metadata: boolean + // has_replication_filter: boolean + // has_snapshot: boolean + // has_unchecked_assembly_data: boolean + // is_date_correlation_view: boolean + // is_dropped_ledger_view: boolean + // is_msh_shipped: boolean + // is_published: boolean + // is_replicated: boolean + // is_schema_published: boolean + // is_tracked_by_cdc: boolean + // ledger_view_type: number + // ledger_view_type_desc: string + // modify_date: Date + name: string + object_id: number + // parent_object_id: number + // principal_id: number | null + schema_id: number + type: 'V ' + // type_desc: 'VIEW' + // with_check_option: boolean + } +} diff --git a/src/dialect/mssql/mssql-query-compiler.ts b/src/dialect/mssql/mssql-query-compiler.ts new file mode 100644 index 000000000..3f68e51d2 --- /dev/null +++ b/src/dialect/mssql/mssql-query-compiler.ts @@ -0,0 +1,91 @@ +import { AddColumnNode } from '../../operation-node/add-column-node.js' +import { AlterTableColumnAlterationNode } from '../../operation-node/alter-table-node.js' +import { DropColumnNode } from '../../operation-node/drop-column-node.js' +import { OffsetNode } from '../../operation-node/offset-node.js' +import { MergeQueryNode } from '../../operation-node/merge-query-node.js' +import { DefaultQueryCompiler } from '../../query-compiler/default-query-compiler.js' + +export class MssqlQueryCompiler extends DefaultQueryCompiler { + protected override getCurrentParameterPlaceholder(): string { + return `@${this.numParameters}` + } + + protected override visitOffset(node: OffsetNode): void { + super.visitOffset(node) + this.append(' rows') + } + + // mssql allows multi-column alterations in a single statement, + // but you can only use the command keyword/s once. + // it also doesn't support multiple kinds of commands in the same + // alter table statement, but we compile that anyway for the sake + // of WYSIWYG. + protected override compileColumnAlterations( + columnAlterations: readonly AlterTableColumnAlterationNode[], + ): void { + const nodesByKind: Partial< + Record< + AlterTableColumnAlterationNode['kind'], + AlterTableColumnAlterationNode[] + > + > = {} + + for (const columnAlteration of columnAlterations) { + if (!nodesByKind[columnAlteration.kind]) { + nodesByKind[columnAlteration.kind] = [] + } + + nodesByKind[columnAlteration.kind]!.push(columnAlteration) + } + + let first = true + + if (nodesByKind.AddColumnNode) { + this.append('add ') + this.compileList(nodesByKind.AddColumnNode) + first = false + } + + // multiple of these are not really supported by mssql, + // but for the sake of WYSIWYG. + if (nodesByKind.AlterColumnNode) { + if (!first) this.append(', ') + this.compileList(nodesByKind.AlterColumnNode) + } + + if (nodesByKind.DropColumnNode) { + if (!first) this.append(', ') + this.append('drop column ') + this.compileList(nodesByKind.DropColumnNode) + } + + // not really supported by mssql, but for the sake of WYSIWYG. + if (nodesByKind.ModifyColumnNode) { + if (!first) this.append(', ') + this.compileList(nodesByKind.ModifyColumnNode) + } + + // not really supported by mssql, but for the sake of WYSIWYG. + if (nodesByKind.RenameColumnNode) { + if (!first) this.append(', ') + this.compileList(nodesByKind.RenameColumnNode) + } + } + + protected override visitAddColumn(node: AddColumnNode): void { + this.visitNode(node.column) + } + + protected override visitDropColumn(node: DropColumnNode): void { + this.visitNode(node.column) + } + + protected override visitMergeQuery(node: MergeQueryNode): void { + super.visitMergeQuery(node) + this.append(';') + } + + protected override announcesNewColumnDataType(): boolean { + return false + } +} diff --git a/src/dialect/mysql/mysql-adapter.ts b/src/dialect/mysql/mysql-adapter.ts index 5dd674f63..eb142a8fa 100644 --- a/src/dialect/mysql/mysql-adapter.ts +++ b/src/dialect/mysql/mysql-adapter.ts @@ -1,6 +1,7 @@ import { Kysely } from '../../kysely.js' import { sql } from '../../raw-builder/sql.js' import { DialectAdapterBase } from '../dialect-adapter-base.js' +import { MigrationLockOptions } from '../dialect-adapter.js' const LOCK_ID = 'ea586330-2c93-47c8-908d-981d9d270f9d' const LOCK_TIMEOUT_SECONDS = 60 * 60 @@ -14,7 +15,10 @@ export class MysqlAdapter extends DialectAdapterBase { return false } - async acquireMigrationLock(db: Kysely): Promise { + async acquireMigrationLock( + db: Kysely, + _opt: MigrationLockOptions, + ): Promise { // Kysely uses a single connection to run the migrations. Because of that, we // can take a lock using `get_lock`. Locks acquired using `get_lock` get // released when the connection is destroyed (session ends) or when the lock @@ -22,11 +26,14 @@ export class MysqlAdapter extends DialectAdapterBase { // released by us after successfull or failed migrations OR it's released by // MySQL if the process gets killed for some reason. await sql`select get_lock(${sql.lit(LOCK_ID)}, ${sql.lit( - LOCK_TIMEOUT_SECONDS + LOCK_TIMEOUT_SECONDS, )})`.execute(db) } - async releaseMigrationLock(db: Kysely): Promise { + async releaseMigrationLock( + db: Kysely, + _opt: MigrationLockOptions, + ): Promise { await sql`select release_lock(${sql.lit(LOCK_ID)})`.execute(db) } } diff --git a/src/dialect/mysql/mysql-dialect-config.ts b/src/dialect/mysql/mysql-dialect-config.ts index ba9c657f3..f6e2ff7fe 100644 --- a/src/dialect/mysql/mysql-dialect-config.ts +++ b/src/dialect/mysql/mysql-dialect-config.ts @@ -31,7 +31,7 @@ export interface MysqlDialectConfig { */ export interface MysqlPool { getConnection( - callback: (error: unknown, connection: MysqlPoolConnection) => void + callback: (error: unknown, connection: MysqlPoolConnection) => void, ): void end(callback: (error: unknown) => void): void } @@ -39,12 +39,12 @@ export interface MysqlPool { export interface MysqlPoolConnection { query( sql: string, - parameters: ReadonlyArray + parameters: ReadonlyArray, ): { stream: (options: MysqlStreamOptions) => MysqlStream } query( sql: string, parameters: ReadonlyArray, - callback: (error: unknown, result: MysqlQueryResult) => void + callback: (error: unknown, result: MysqlQueryResult) => void, ): void release(): void } @@ -60,6 +60,7 @@ export interface MysqlStream { export interface MysqlOkPacket { affectedRows: number + changedRows: number insertId: number } diff --git a/src/dialect/mysql/mysql-driver.ts b/src/dialect/mysql/mysql-driver.ts index 8e37757b5..f03067957 100644 --- a/src/dialect/mysql/mysql-driver.ts +++ b/src/dialect/mysql/mysql-driver.ts @@ -64,14 +64,14 @@ export class MysqlDriver implements Driver { async beginTransaction( connection: DatabaseConnection, - settings: TransactionSettings + settings: TransactionSettings, ): Promise { if (settings.isolationLevel) { // On MySQL this sets the isolation level of the next transaction. await connection.executeQuery( CompiledQuery.raw( - `set transaction isolation level ${settings.isolationLevel}` - ) + `set transaction isolation level ${settings.isolationLevel}`, + ), ) } @@ -119,13 +119,18 @@ class MysqlConnection implements DatabaseConnection { const result = await this.#executeQuery(compiledQuery) if (isOkPacket(result)) { - const { insertId, affectedRows } = result + const { insertId, affectedRows, changedRows } = result const numAffectedRows = affectedRows !== undefined && affectedRows !== null ? BigInt(affectedRows) : undefined + const numChangedRows = + changedRows !== undefined && changedRows !== null + ? BigInt(changedRows) + : undefined + return { insertId: insertId !== undefined && @@ -136,6 +141,7 @@ class MysqlConnection implements DatabaseConnection { // TODO: remove. numUpdatedOrDeletedRows: numAffectedRows, numAffectedRows, + numChangedRows, rows: [], } } else if (Array.isArray(result)) { @@ -163,14 +169,14 @@ class MysqlConnection implements DatabaseConnection { } else { resolve(result) } - } + }, ) }) } async *streamQuery( compiledQuery: CompiledQuery, - _chunkSize: number + _chunkSize: number, ): AsyncIterableIterator> { const stream = this.#rawConnection .query(compiledQuery.sql, compiledQuery.parameters) diff --git a/src/dialect/mysql/mysql-introspector.ts b/src/dialect/mysql/mysql-introspector.ts index 19dd3f836..d407361d0 100644 --- a/src/dialect/mysql/mysql-introspector.ts +++ b/src/dialect/mysql/mysql-introspector.ts @@ -31,7 +31,7 @@ export class MysqlIntrospector implements DatabaseIntrospector { } async getTables( - options: DatabaseMetadataOptions = { withInternalKyselyTables: false } + options: DatabaseMetadataOptions = { withInternalKyselyTables: false }, ): Promise { let query = this.#db .selectFrom('information_schema.columns as columns') @@ -39,7 +39,7 @@ export class MysqlIntrospector implements DatabaseIntrospector { b .onRef('columns.TABLE_CATALOG', '=', 'tables.TABLE_CATALOG') .onRef('columns.TABLE_SCHEMA', '=', 'tables.TABLE_SCHEMA') - .onRef('columns.TABLE_NAME', '=', 'tables.TABLE_NAME') + .onRef('columns.TABLE_NAME', '=', 'tables.TABLE_NAME'), ) .select([ 'columns.COLUMN_NAME', @@ -50,6 +50,7 @@ export class MysqlIntrospector implements DatabaseIntrospector { 'columns.IS_NULLABLE', 'columns.DATA_TYPE', 'columns.EXTRA', + 'columns.COLUMN_COMMENT', ]) .where('columns.TABLE_SCHEMA', '=', sql`database()`) .orderBy('columns.TABLE_NAME') @@ -67,7 +68,7 @@ export class MysqlIntrospector implements DatabaseIntrospector { } async getMetadata( - options?: DatabaseMetadataOptions + options?: DatabaseMetadataOptions, ): Promise { return { tables: await this.getTables(options), @@ -96,7 +97,8 @@ export class MysqlIntrospector implements DatabaseIntrospector { isNullable: it.IS_NULLABLE === 'YES', isAutoIncrementing: it.EXTRA.toLowerCase().includes('auto_increment'), hasDefaultValue: it.COLUMN_DEFAULT !== null, - }) + comment: it.COLUMN_COMMENT === '' ? undefined : it.COLUMN_COMMENT, + }), ) return tables @@ -117,4 +119,5 @@ interface RawColumnMetadata { IS_NULLABLE: 'YES' | 'NO' DATA_TYPE: string EXTRA: string + COLUMN_COMMENT: string } diff --git a/src/dialect/mysql/mysql-query-compiler.ts b/src/dialect/mysql/mysql-query-compiler.ts index 5aefd4d97..019f1c2bf 100644 --- a/src/dialect/mysql/mysql-query-compiler.ts +++ b/src/dialect/mysql/mysql-query-compiler.ts @@ -1,3 +1,4 @@ +import { CreateIndexNode } from '../../operation-node/create-index-node.js' import { DefaultQueryCompiler } from '../../query-compiler/default-query-compiler.js' const ID_WRAP_REGEX = /`/g @@ -34,4 +35,41 @@ export class MysqlQueryCompiler extends DefaultQueryCompiler { protected override sanitizeIdentifier(identifier: string): string { return identifier.replace(ID_WRAP_REGEX, '``') } + + protected override visitCreateIndex(node: CreateIndexNode): void { + this.append('create ') + + if (node.unique) { + this.append('unique ') + } + + this.append('index ') + + if (node.ifNotExists) { + this.append('if not exists ') + } + + this.visitNode(node.name) + + if (node.using) { + this.append(' using ') + this.visitNode(node.using) + } + + if (node.table) { + this.append(' on ') + this.visitNode(node.table) + } + + if (node.columns) { + this.append(' (') + this.compileList(node.columns) + this.append(')') + } + + if (node.where) { + this.append(' ') + this.visitNode(node.where) + } + } } diff --git a/src/dialect/postgres/postgres-adapter.ts b/src/dialect/postgres/postgres-adapter.ts index 2a93cd008..e49400f05 100644 --- a/src/dialect/postgres/postgres-adapter.ts +++ b/src/dialect/postgres/postgres-adapter.ts @@ -1,6 +1,7 @@ import { Kysely } from '../../kysely.js' import { sql } from '../../raw-builder/sql.js' import { DialectAdapterBase } from '../dialect-adapter-base.js' +import { MigrationLockOptions } from '../dialect-adapter.js' // Random id for our transaction lock. const LOCK_ID = BigInt('3853314791062309107') @@ -14,12 +15,18 @@ export class PostgresAdapter extends DialectAdapterBase { return true } - async acquireMigrationLock(db: Kysely): Promise { + async acquireMigrationLock( + db: Kysely, + _opt: MigrationLockOptions, + ): Promise { // Acquire a transaction level advisory lock. await sql`select pg_advisory_xact_lock(${sql.lit(LOCK_ID)})`.execute(db) } - async releaseMigrationLock(): Promise { + async releaseMigrationLock( + _db: Kysely, + _opt: MigrationLockOptions, + ): Promise { // Nothing to do here. `pg_advisory_xact_lock` is automatically released at the // end of the transaction and since `supportsTransactionalDdl` true, we know // the `db` instance passed to acquireMigrationLock is actually a transaction. diff --git a/src/dialect/postgres/postgres-dialect-config.ts b/src/dialect/postgres/postgres-dialect-config.ts index b0ff1f4fe..1f04ff945 100644 --- a/src/dialect/postgres/postgres-dialect-config.ts +++ b/src/dialect/postgres/postgres-dialect-config.ts @@ -9,7 +9,7 @@ export interface PostgresDialectConfig { * * If a function is provided, it's called once when the first query is executed. * - * https://node-postgres.com/api/pool + * https://node-postgres.com/apis/pool */ pool: PostgresPool | (() => Promise) @@ -39,7 +39,7 @@ export interface PostgresDialectConfig { * * We don't use the type from `pg` here to not have a dependency to it. * - * https://node-postgres.com/api/pool + * https://node-postgres.com/apis/pool */ export interface PostgresPool { connect(): Promise @@ -49,7 +49,7 @@ export interface PostgresPool { export interface PostgresPoolClient { query( sql: string, - parameters: ReadonlyArray + parameters: ReadonlyArray, ): Promise> query(cursor: PostgresCursor): PostgresCursor release(): void @@ -62,11 +62,11 @@ export interface PostgresCursor { export type PostgresCursorConstructor = new ( sql: string, - parameters: unknown[] + parameters: unknown[], ) => PostgresCursor export interface PostgresQueryResult { - command: 'UPDATE' | 'DELETE' | 'INSERT' | 'SELECT' + command: 'UPDATE' | 'DELETE' | 'INSERT' | 'SELECT' | 'MERGE' rowCount: number rows: R[] } diff --git a/src/dialect/postgres/postgres-driver.ts b/src/dialect/postgres/postgres-driver.ts index ae070d1f6..70d8a4bfb 100644 --- a/src/dialect/postgres/postgres-driver.ts +++ b/src/dialect/postgres/postgres-driver.ts @@ -43,7 +43,7 @@ export class PostgresDriver implements Driver { // The driver must take care of calling `onCreateConnection` when a new // connection is created. The `pg` module doesn't provide an async hook // for the connection creation. We need to call the method explicitly. - if (this.#config?.onCreateConnection) { + if (this.#config.onCreateConnection) { await this.#config.onCreateConnection(connection) } } @@ -53,13 +53,13 @@ export class PostgresDriver implements Driver { async beginTransaction( connection: DatabaseConnection, - settings: TransactionSettings + settings: TransactionSettings, ): Promise { if (settings.isolationLevel) { await connection.executeQuery( CompiledQuery.raw( - `start transaction isolation level ${settings.isolationLevel}` - ) + `start transaction isolation level ${settings.isolationLevel}`, + ), ) } else { await connection.executeQuery(CompiledQuery.raw('begin')) @@ -109,7 +109,8 @@ class PostgresConnection implements DatabaseConnection { if ( result.command === 'INSERT' || result.command === 'UPDATE' || - result.command === 'DELETE' + result.command === 'DELETE' || + result.command === 'MERGE' ) { const numAffectedRows = BigInt(result.rowCount) @@ -131,11 +132,11 @@ class PostgresConnection implements DatabaseConnection { async *streamQuery( compiledQuery: CompiledQuery, - chunkSize: number + chunkSize: number, ): AsyncIterableIterator> { if (!this.#options.cursor) { throw new Error( - "'cursor' is not present in your postgres dialect config. It's required to make streaming work in postgres." + "'cursor' is not present in your postgres dialect config. It's required to make streaming work in postgres.", ) } @@ -146,8 +147,8 @@ class PostgresConnection implements DatabaseConnection { const cursor = this.#client.query( new this.#options.cursor( compiledQuery.sql, - compiledQuery.parameters.slice() - ) + compiledQuery.parameters.slice(), + ), ) try { diff --git a/src/dialect/postgres/postgres-introspector.ts b/src/dialect/postgres/postgres-introspector.ts index ddfec15a7..6a359057f 100644 --- a/src/dialect/postgres/postgres-introspector.ts +++ b/src/dialect/postgres/postgres-introspector.ts @@ -31,7 +31,7 @@ export class PostgresIntrospector implements DatabaseIntrospector { } async getTables( - options: DatabaseMetadataOptions = { withInternalKyselyTables: false } + options: DatabaseMetadataOptions = { withInternalKyselyTables: false }, ): Promise { let query = this.#db // column @@ -46,7 +46,7 @@ export class PostgresIntrospector implements DatabaseIntrospector { .innerJoin( 'pg_catalog.pg_namespace as dtns', 'typ.typnamespace', - 'dtns.oid' + 'dtns.oid', ) .select([ 'a.attname as column', @@ -57,7 +57,9 @@ export class PostgresIntrospector implements DatabaseIntrospector { 'ns.nspname as schema', 'typ.typname as type', 'dtns.nspname as type_schema', - + sql`col_description(a.attrelid, a.attnum)`.as( + 'column_description', + ), // Detect if the column is auto incrementing by finding the sequence // that is created for `serial` and `bigserial` columns. this.#db @@ -70,10 +72,9 @@ export class PostgresIntrospector implements DatabaseIntrospector { .as('auto_incrementing'), ]) // r == normal table - .where(({ cmpr, or }) => or([ - cmpr('c.relkind', '=', 'r'), - cmpr('c.relkind', '=', 'v'), - ])) + .where((eb) => + eb.or([eb('c.relkind', '=', 'r'), eb('c.relkind', '=', 'v')]), + ) .where('ns.nspname', '!~', '^pg_') .where('ns.nspname', '!=', 'information_schema') // No system columns @@ -95,7 +96,7 @@ export class PostgresIntrospector implements DatabaseIntrospector { } async getMetadata( - options?: DatabaseMetadataOptions + options?: DatabaseMetadataOptions, ): Promise { return { tables: await this.getTables(options), @@ -105,7 +106,7 @@ export class PostgresIntrospector implements DatabaseIntrospector { #parseTableMetadata(columns: RawColumnMetadata[]): TableMetadata[] { return columns.reduce((tables, it) => { let table = tables.find( - (tbl) => tbl.name === it.table && tbl.schema === it.schema + (tbl) => tbl.name === it.table && tbl.schema === it.schema, ) if (!table) { @@ -127,7 +128,8 @@ export class PostgresIntrospector implements DatabaseIntrospector { isNullable: !it.not_null, isAutoIncrementing: !!it.auto_incrementing, hasDefaultValue: it.has_default, - }) + comment: it.column_description ?? undefined, + }), ) return tables @@ -149,4 +151,5 @@ interface RawColumnMetadata { type: string type_schema: string auto_incrementing: boolean | null + column_description: string | null } diff --git a/src/dialect/sqlite/sqlite-adapter.ts b/src/dialect/sqlite/sqlite-adapter.ts index 189c39d5c..74745c50b 100644 --- a/src/dialect/sqlite/sqlite-adapter.ts +++ b/src/dialect/sqlite/sqlite-adapter.ts @@ -1,6 +1,8 @@ +import { Kysely } from '../../kysely.js' import { DialectAdapterBase } from '../dialect-adapter-base.js' +import { MigrationLockOptions } from '../dialect-adapter.js' -export class SqliteAdapter implements DialectAdapterBase { +export class SqliteAdapter extends DialectAdapterBase { get supportsTransactionalDdl(): boolean { return false } @@ -9,13 +11,19 @@ export class SqliteAdapter implements DialectAdapterBase { return true } - async acquireMigrationLock(): Promise { + async acquireMigrationLock( + _db: Kysely, + _opt: MigrationLockOptions, + ): Promise { // SQLite only has one connection that's reserved by the migration system // for the whole time between acquireMigrationLock and releaseMigrationLock. // We don't need to do anything here. } - async releaseMigrationLock(): Promise { + async releaseMigrationLock( + _db: Kysely, + _opt: MigrationLockOptions, + ): Promise { // SQLite only has one connection that's reserved by the migration system // for the whole time between acquireMigrationLock and releaseMigrationLock. // We don't need to do anything here. diff --git a/src/dialect/sqlite/sqlite-dialect-config.ts b/src/dialect/sqlite/sqlite-dialect-config.ts index 3b7ac0511..f9c6d90d7 100644 --- a/src/dialect/sqlite/sqlite-dialect-config.ts +++ b/src/dialect/sqlite/sqlite-dialect-config.ts @@ -41,4 +41,5 @@ export interface SqliteStatement { changes: number | bigint lastInsertRowid: number | bigint } + iterate(parameters: ReadonlyArray): IterableIterator } diff --git a/src/dialect/sqlite/sqlite-driver.ts b/src/dialect/sqlite/sqlite-driver.ts index 510848a1c..dcfbca2e6 100644 --- a/src/dialect/sqlite/sqlite-driver.ts +++ b/src/dialect/sqlite/sqlite-driver.ts @@ -3,6 +3,7 @@ import { QueryResult, } from '../../driver/database-connection.js' import { Driver } from '../../driver/driver.js' +import { SelectQueryNode } from '../../operation-node/select-query-node.js' import { CompiledQuery } from '../../query-compiler/compiled-query.js' import { freeze, isFunction } from '../../util/object-utils.js' import { SqliteDatabase, SqliteDialectConfig } from './sqlite-dialect-config.js' @@ -92,8 +93,22 @@ class SqliteConnection implements DatabaseConnection { } } - async *streamQuery(): AsyncIterableIterator> { - throw new Error("Sqlite driver doesn't support streaming") + async *streamQuery( + compiledQuery: CompiledQuery, + _chunkSize: number, + ): AsyncIterableIterator> { + const { sql, parameters, query } = compiledQuery + const stmt = this.#db.prepare(sql) + if (SelectQueryNode.is(query)) { + const iter = stmt.iterate(parameters) as IterableIterator + for (const row of iter) { + yield { + rows: [row], + } + } + } else { + throw new Error('Sqlite driver only supports streaming of select queries') + } } } diff --git a/src/dialect/sqlite/sqlite-introspector.ts b/src/dialect/sqlite/sqlite-introspector.ts index c2ccf358c..9d09b6737 100644 --- a/src/dialect/sqlite/sqlite-introspector.ts +++ b/src/dialect/sqlite/sqlite-introspector.ts @@ -25,10 +25,10 @@ export class SqliteIntrospector implements DatabaseIntrospector { } async getTables( - options: DatabaseMetadataOptions = { withInternalKyselyTables: false } + options: DatabaseMetadataOptions = { withInternalKyselyTables: false }, ): Promise { let query = this.#db - .selectFrom('sqlite_schema') + .selectFrom('sqlite_master') .where('type', 'in', ['table', 'view']) .where('name', 'not like', 'sqlite_%') .select('name') @@ -46,7 +46,7 @@ export class SqliteIntrospector implements DatabaseIntrospector { } async getMetadata( - options?: DatabaseMetadataOptions + options?: DatabaseMetadataOptions, ): Promise { return { tables: await this.getTables(options), @@ -79,7 +79,7 @@ export class SqliteIntrospector implements DatabaseIntrospector { type: string notnull: 0 | 1 dflt_value: any - }>`pragma_table_info(${table})`.as('table_info') + }>`pragma_table_info(${table})`.as('table_info'), ) .select(['name', 'type', 'notnull', 'dflt_value']) .orderBy('cid') @@ -94,6 +94,7 @@ export class SqliteIntrospector implements DatabaseIntrospector { isNullable: !col.notnull, isAutoIncrementing: col.name === autoIncrementCol, hasDefaultValue: col.dflt_value != null, + comment: undefined, })), } } diff --git a/src/driver/connection-provider.ts b/src/driver/connection-provider.ts index a5110b5a7..969fe74c5 100644 --- a/src/driver/connection-provider.ts +++ b/src/driver/connection-provider.ts @@ -6,6 +6,6 @@ export interface ConnectionProvider { * the connection after the callback has been run. */ provideConnection( - consumer: (connection: DatabaseConnection) => Promise + consumer: (connection: DatabaseConnection) => Promise, ): Promise } diff --git a/src/driver/database-connection.ts b/src/driver/database-connection.ts index 17a1c6646..1259a77c2 100644 --- a/src/driver/database-connection.ts +++ b/src/driver/database-connection.ts @@ -9,7 +9,7 @@ export interface DatabaseConnection { executeQuery(compiledQuery: CompiledQuery): Promise> streamQuery( compiledQuery: CompiledQuery, - chunkSize?: number + chunkSize?: number, ): AsyncIterableIterator> } @@ -21,11 +21,18 @@ export interface QueryResult { readonly numUpdatedOrDeletedRows?: bigint /** - * This is defined for insert, update and delete queries and contains + * This is defined for insert, update, delete and merge queries and contains * the number of rows the query inserted/updated/deleted. */ readonly numAffectedRows?: bigint + /** + * This is defined for update queries and contains the number of rows + * the query changed. + * This is optional and only provided by some drivers like node-mysql2. + */ + readonly numChangedRows?: bigint + /** * This is defined for insert queries on dialects that return * the auto incrementing primary key from an insert. diff --git a/src/driver/default-connection-provider.ts b/src/driver/default-connection-provider.ts index 386c8bf18..8aa9f4d39 100644 --- a/src/driver/default-connection-provider.ts +++ b/src/driver/default-connection-provider.ts @@ -10,7 +10,7 @@ export class DefaultConnectionProvider implements ConnectionProvider { } async provideConnection( - consumer: (connection: DatabaseConnection) => Promise + consumer: (connection: DatabaseConnection) => Promise, ): Promise { const connection = await this.#driver.acquireConnection() diff --git a/src/driver/driver.ts b/src/driver/driver.ts index c5f9d9ed6..ef9214d17 100644 --- a/src/driver/driver.ts +++ b/src/driver/driver.ts @@ -24,7 +24,7 @@ export interface Driver { */ beginTransaction( connection: DatabaseConnection, - settings: TransactionSettings + settings: TransactionSettings, ): Promise /** @@ -57,6 +57,7 @@ export const TRANSACTION_ISOLATION_LEVELS = [ 'read committed', 'repeatable read', 'serializable', + 'snapshot', ] as const export type IsolationLevel = ArrayItemType diff --git a/src/driver/runtime-driver.ts b/src/driver/runtime-driver.ts index 707e25e4e..a7ba8d771 100644 --- a/src/driver/runtime-driver.ts +++ b/src/driver/runtime-driver.ts @@ -14,27 +14,44 @@ export class RuntimeDriver implements Driver { readonly #log: Log #initPromise?: Promise + #initDone: boolean #destroyPromise?: Promise #connections = new WeakSet() constructor(driver: Driver, log: Log) { + this.#initDone = false this.#driver = driver this.#log = log } async init(): Promise { + if (this.#destroyPromise) { + throw new Error('driver has already been destroyed') + } + if (!this.#initPromise) { - this.#initPromise = this.#driver.init().catch((err) => { - this.#initPromise = undefined - return Promise.reject(err) - }) + this.#initPromise = this.#driver + .init() + .then(() => { + this.#initDone = true + }) + .catch((err) => { + this.#initPromise = undefined + return Promise.reject(err) + }) } await this.#initPromise } async acquireConnection(): Promise { - await this.init() + if (this.#destroyPromise) { + throw new Error('driver has already been destroyed') + } + + if (!this.#initDone) { + await this.init() + } const connection = await this.#driver.acquireConnection() @@ -55,7 +72,7 @@ export class RuntimeDriver implements Driver { beginTransaction( connection: DatabaseConnection, - settings: TransactionSettings + settings: TransactionSettings, ): Promise { return this.#driver.beginTransaction(connection, settings) } @@ -98,17 +115,21 @@ export class RuntimeDriver implements Driver { const executeQuery = connection.executeQuery connection.executeQuery = async ( - compiledQuery + compiledQuery, ): Promise> => { + let caughtError: unknown const startTime = performanceNow() try { return await executeQuery.call(connection, compiledQuery) } catch (error) { + caughtError = error await this.#logError(error, compiledQuery, startTime) throw error } finally { - await this.#logQuery(compiledQuery, startTime) + if (!caughtError) { + await this.#logQuery(compiledQuery, startTime) + } } } } @@ -116,7 +137,7 @@ export class RuntimeDriver implements Driver { async #logError( error: unknown, compiledQuery: CompiledQuery, - startTime: number + startTime: number, ): Promise { await this.#log.error(() => ({ level: 'error', @@ -128,7 +149,7 @@ export class RuntimeDriver implements Driver { async #logQuery( compiledQuery: CompiledQuery, - startTime: number + startTime: number, ): Promise { await this.#log.query(() => ({ level: 'query', diff --git a/src/driver/single-connection-provider.ts b/src/driver/single-connection-provider.ts index 3bafd761a..eb5a28022 100644 --- a/src/driver/single-connection-provider.ts +++ b/src/driver/single-connection-provider.ts @@ -1,38 +1,37 @@ import { DatabaseConnection } from './database-connection.js' import { ConnectionProvider } from './connection-provider.js' +const ignoreError = () => {} + export class SingleConnectionProvider implements ConnectionProvider { readonly #connection: DatabaseConnection - #runningPromise?: Promise + #runningPromise?: Promise constructor(connection: DatabaseConnection) { this.#connection = connection } async provideConnection( - consumer: (connection: DatabaseConnection) => Promise + consumer: (connection: DatabaseConnection) => Promise, ): Promise { while (this.#runningPromise) { - await this.#runningPromise + await this.#runningPromise.catch(ignoreError) } - const promise = this.#run(consumer) - - this.#runningPromise = promise - .then(() => { - this.#runningPromise = undefined - }) - .catch(() => { - this.#runningPromise = undefined - }) + // `#runningPromise` must be set to undefined before it's + // resolved or rejected. Otherwise the while loop above + // will misbehave. + this.#runningPromise = this.#run(consumer).finally(() => { + this.#runningPromise = undefined + }) - return promise + return this.#runningPromise } // Run the runner in an async function to make sure it doesn't // throw synchronous errors. async #run( - runner: (connection: DatabaseConnection) => Promise + runner: (connection: DatabaseConnection) => Promise, ): Promise { return await runner(this.#connection) } diff --git a/src/dynamic/dynamic-reference-builder.ts b/src/dynamic/dynamic-reference-builder.ts index 122dd23da..f09f4027a 100644 --- a/src/dynamic/dynamic-reference-builder.ts +++ b/src/dynamic/dynamic-reference-builder.ts @@ -37,7 +37,7 @@ export class DynamicReferenceBuilder } export function isDynamicReferenceBuilder( - obj: unknown + obj: unknown, ): obj is DynamicReferenceBuilder { return ( isObject(obj) && diff --git a/src/dynamic/dynamic.ts b/src/dynamic/dynamic.ts index 4c2b1e795..6e6f5b82b 100644 --- a/src/dynamic/dynamic.ts +++ b/src/dynamic/dynamic.ts @@ -70,7 +70,7 @@ export class DynamicModule { * * const [person] = await db.selectFrom('person') * .select([ - * ref(columnFromUserInput), + * ref(columnFromUserInput), * 'id' * ]) * .execute() diff --git a/src/expression/expression-builder.ts b/src/expression/expression-builder.ts index 5ff308322..a5baf7277 100644 --- a/src/expression/expression-builder.ts +++ b/src/expression/expression-builder.ts @@ -1,4 +1,7 @@ -import { SelectQueryBuilder } from '../query-builder/select-query-builder.js' +import { + SelectQueryBuilder, + createSelectQueryBuilder, +} from '../query-builder/select-query-builder.js' import { SelectQueryNode } from '../operation-node/select-query-node.js' import { parseTableExpressionOrList, @@ -9,6 +12,7 @@ import { ExtractTableAlias, AnyAliasedTable, PickTableWithAlias, + parseTable, } from '../parser/table-parser.js' import { WithSchemaPlugin } from '../plugin/with-schema/with-schema-plugin.js' import { createQueryId } from '../util/query-id.js' @@ -18,6 +22,7 @@ import { } from '../query-builder/function-module.js' import { ExtractTypeFromReferenceExpression, + parseJSONReference, parseReferenceExpression, parseStringReference, ReferenceExpression, @@ -27,33 +32,174 @@ import { import { QueryExecutor } from '../query-executor/query-executor.js' import { BinaryOperatorExpression, - ComparisonOperatorExpression, + FilterObject, OperandValueExpression, OperandValueExpressionOrList, + parseFilterList, + parseFilterObject, parseValueBinaryOperation, + parseValueBinaryOperationOrExpression, } from '../parser/binary-operation-parser.js' import { Expression } from './expression.js' -import { AndNode } from '../operation-node/and-node.js' -import { OrNode } from '../operation-node/or-node.js' import { ParensNode } from '../operation-node/parens-node.js' import { ExpressionWrapper } from './expression-wrapper.js' import { ComparisonOperator, + JSONOperatorWith$, + OperatorNode, UnaryOperator, } from '../operation-node/operator-node.js' -import { SqlBool } from '../util/type-utils.js' +import { IsNever, SqlBool } from '../util/type-utils.js' import { parseUnaryOperation } from '../parser/unary-operation-parser.js' import { - ExtractTypeFromValueExpressionOrList, - parseValueExpressionOrList, + ExtractTypeFromValueExpression, + parseSafeImmediateValue, + parseValueExpression, } from '../parser/value-parser.js' import { NOOP_QUERY_EXECUTOR } from '../query-executor/noop-query-executor.js' -import { ValueNode } from '../operation-node/value-node.js' import { CaseBuilder } from '../query-builder/case-builder.js' import { CaseNode } from '../operation-node/case-node.js' -import { isUndefined } from '../util/object-utils.js' +import { isReadonlyArray, isUndefined } from '../util/object-utils.js' +import { JSONPathBuilder } from '../query-builder/json-path-builder.js' +import { OperandExpression } from '../parser/expression-parser.js' +import { BinaryOperationNode } from '../operation-node/binary-operation-node.js' +import { AndNode } from '../operation-node/and-node.js' +import { + RefTuple2, + RefTuple3, + RefTuple4, + RefTuple5, + ValTuple2, + ValTuple3, + ValTuple4, + ValTuple5, +} from '../parser/tuple-parser.js' +import { TupleNode } from '../operation-node/tuple-node.js' +import { Selectable } from '../util/column-type.js' +import { JSONPathNode } from '../operation-node/json-path-node.js' +import { KyselyTypeError } from '../util/type-error.js' +import { + DataTypeExpression, + parseDataTypeExpression, +} from '../parser/data-type-parser.js' +import { CastNode } from '../operation-node/cast-node.js' export interface ExpressionBuilder { + /** + * 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 + * eb.selectFrom('person') + * .selectAll() + * .where((eb) => eb('first_name', '=', 'Jennifer')) + * ``` + * + * 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 + * eb.selectFrom('person') + * .selectAll() + * .where((eb) => eb('first_name', '=', eb.ref('last_name'))) + * ``` + * + * 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 + * db.updateTable('person') + * .set((eb) => ({ + * age: eb('age', '+', 1) + * })) + * .where('id', '=', id) + * ``` + * + * 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 + * eb.selectFrom('person') + * .selectAll() + * .where((eb) => eb( + * eb.fn('lower', ['first_name']), + * 'in', + * eb.selectFrom('pet') + * .select('pet.name') + * .where('pet.species', '=', 'cat') + * )) + * ``` + */ + < + RE extends ReferenceExpression, + OP extends BinaryOperatorExpression, + VE extends OperandValueExpressionOrList, + >( + lhs: RE, + op: OP, + rhs: VE, + ): ExpressionWrapper< + DB, + TB, + OP extends ComparisonOperator + ? SqlBool + : ExtractTypeFromReferenceExpression + > + + /** + * Returns a copy of `this` expression builder, for destructuring purposes. + * + * ### Examples + * + * ```ts + * db.selectFrom('person') + * .where(({ eb, exists, selectFrom }) => + * eb('first_name', '=', 'Jennifer').and( + * exists(selectFrom('pet').whereRef('owner_id', '=', 'person.id').select('pet.id')) + * ) + * ) + * .selectAll() + * ``` + * + * 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 + /** * Returns a {@link FunctionModule} that can be used to write type safe function * calls. @@ -71,7 +217,7 @@ export interface ExpressionBuilder { * eb.fn.count('pet.id').as('pet_count') * ]) * .groupBy('person.id') - * .having(count('pet.id'), '>', 10) + * .having((eb) => eb.fn.count('pet.id'), '>', 10) * .execute() * ``` * @@ -132,27 +278,27 @@ export interface ExpressionBuilder { * because `pet` is not joined to that query. */ selectFrom( - from: TE[] + from: TE[], ): SelectQueryBuilder, {}> selectFrom>( - from: TE[] + from: TE[], ): SelectQueryBuilder, FromTables, {}> selectFrom( - from: TE + from: TE, ): SelectQueryBuilder, {}> selectFrom>( - from: TE + from: TE, ): SelectQueryBuilder< DB & PickTableWithAlias, - TB | ExtractTableAlias, + TB | ExtractTableAlias, TE>, {} > selectFrom>( - from: TE + from: TE, ): SelectQueryBuilder, FromTables, {}> /** @@ -177,7 +323,7 @@ export interface ExpressionBuilder { * .when('gender', '=', 'female') * .then( * eb - * .case('martialStatus') + * .case('maritalStatus') * .when('single') * .then('Ms.') * .else('Mrs.') @@ -197,7 +343,7 @@ export interface ExpressionBuilder { * case * when "gender" = $1 then $2 * when "gender" = $3 then - * case "martialStatus" + * case "maritalStatus" * when $4 then $5 * else $6 * end @@ -209,31 +355,37 @@ export interface ExpressionBuilder { case(): CaseBuilder case>( - column: C + column: C, ): CaseBuilder> - case(expression: Expression): CaseBuilder + case>( + expression: E, + ): CaseBuilder> /** - * This can be used to reference columns. + * 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 {@link bxp} and {@link cmpr} is a value. + * By default the third argument of binary expressions is a value. * This function can be used to pass in a column reference instead: * * ```ts * db.selectFrom('person') * .selectAll('person') - * .where(({ or, cmpr, ref }) => or([ - * cmpr('first_name', '=', ref('last_name')), - * cmpr('first_name', '=', ref('middle_name')) + * .where((eb) => eb.or([ + * eb('first_name', '=', eb.ref('last_name')), + * eb('first_name', '=', eb.ref('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: + * 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 * db.insertInto('person') @@ -247,18 +399,116 @@ export interface ExpressionBuilder { * ) * ``` * - * 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: + * 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 * db.update('pet').set((eb) => ({ - * name: sql`concat(${eb.ref('pet.name')}, ${suffix})` + * name: sql`concat(${eb.ref('pet.name')}, ${suffix})` * })) * ``` + * + * In the next example we use `ref` to reference a nested JSON property: + * + * ```ts + * db.selectFrom('person') + * .where(({ eb, ref }) => eb( + * ref('address', '->').key('state').key('abbr'), + * '=', + * 'CA' + * )) + * .selectAll() + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * select * from "person" where "address"->'state'->'abbr' = $1 + * ``` + * + * You can also compile to a JSON path expression by using the `->$`or `->>$` operator: + * + * ```ts + * db.selectFrom('person') + * .select(({ ref }) => + * ref('experience', '->$') + * .at('last') + * .key('title') + * .as('current_job') + * ) + * ``` + * + * The generated SQL (MySQL): + * + * ```sql + * select `experience`->'$[last].title' as `current_job` from `person` + * ``` */ ref>( - reference: RE - ): ExpressionWrapper> + reference: RE, + ): ExpressionWrapper> + + ref>( + reference: RE, + op: JSONOperatorWith$, + ): JSONPathBuilder> + + /** + * Creates a JSON path expression with provided column as root document (the $). + * + * For a JSON reference expression, see {@link ref}. + * + * ### Examples + * + * ```ts + * db.updateTable('person') + * .set('experience', (eb) => eb.fn('json_set', [ + * 'experience', + * eb.jsonPath<'experience'>().at('last').key('title'), + * eb.val('CEO') + * ])) + * .where('id', '=', id) + * .execute() + * ``` + * + * The generated SQL (MySQL): + * + * ```sql + * update `person` + * set `experience` = json_set(`experience`, '$[last].title', ?) + * where `id` = ? + * ``` + */ + jsonPath<$ extends StringReference = never>(): IsNever<$> extends true + ? KyselyTypeError<"You must provide a column reference as this method's $ generic"> + : JSONPathBuilder> + + /** + * Creates a table reference. + * + * ```ts + * db.selectFrom('person') + * .innerJoin('pet', 'pet.owner_id', 'person.id') + * .select(eb => [ + * 'person.id', + * sql`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" + * ``` + */ + table( + table: T, + ): ExpressionWrapper> /** * Returns a value expression. @@ -269,11 +519,11 @@ export interface ExpressionBuilder { * * ### Examples * - * The {@link cmpr} function takes a reference by default as the first argument. `val` could + * Binary expressions take a reference by default as the first argument. `val` could * be used to pass in a value instead: * * ```ts - * cmpr(val(38), '=', ref('age')) + * eb(val(38), '=', ref('age')) * ``` * * The generated SQL (PostgreSQL): @@ -283,131 +533,210 @@ export interface ExpressionBuilder { * ``` */ val( - value: VE - ): ExpressionWrapper> + value: VE, + ): ExpressionWrapper> /** - * Creates a binary comparison expression. + * Creates a tuple 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 bxp} + * This creates a tuple using column references by default. See {@link tuple} + * if you need to create value tuples. * * ### Examples * - * In this example we use `cmpr` and {@link or} to create a `WHERE expr1 OR expr2 OR expr3` - * statement: - * * ```ts * db.selectFrom('person') * .selectAll('person') - * .where(({ or, cmpr }) => or([ - * cmpr('first_name', '=', 'Jennifer'), - * cmpr('fist_name', '=', 'Arnold'), - * cmpr('fist_name', '=', 'Sylvester') - * ])) + * .where(({ eb, refTuple, tuple }) => eb( + * refTuple('first_name', 'last_name'), + * 'in', + * [ + * tuple('Jennifer', 'Aniston'), + * tuple('Sylvester', 'Stallone') + * ] + * )) * ``` * * The generated SQL (PostgreSQL): * * ```sql - * select "person".* - * from "person" - * where "first_name" = $1 - * or "first_name" = $2 - * or "first_name" = $3 + * select + * "person".* + * from + * "person" + * where + * ("first_name", "last_name") + * in + * ( + * ($1, $2), + * ($3, $4) + * ) * ``` * - * By default the third argument is a value. {@link ref} can be used to - * pass in a column reference instead: + * 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 * db.selectFrom('person') * .selectAll('person') - * .where(({ or, cmpr, ref }) => or([ - * cmpr('first_name', '=', ref('last_name')), - * cmpr('first_name', '=', ref('middle_name')) - * ])) + * .where(({ eb, refTuple, selectFrom }) => eb( + * refTuple('first_name', 'last_name'), + * 'in', + * selectFrom('pet') + * .select(['name', 'species']) + * .where('species', '!=', 'cat') + * .$asTuple('name', 'species') + * )) * ``` * * The generated SQL (PostgreSQL): * * ```sql - * select "person".* - * from "person" - * where "first_name" = "last_name" - * or "first_name" = "middle_name" + * select + * "person".* + * from + * "person" + * where + * ("first_name", "last_name") + * in + * ( + * select "name", "species" + * from "pet" + * where "species" != $1 + * ) * ``` */ - cmpr< - O extends SqlBool = SqlBool, - RE extends ReferenceExpression = ReferenceExpression + refTuple< + R1 extends ReferenceExpression, + R2 extends ReferenceExpression, >( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): ExpressionWrapper + value1: R1, + value2: R2, + ): ExpressionWrapper> + + refTuple< + R1 extends ReferenceExpression, + R2 extends ReferenceExpression, + R3 extends ReferenceExpression, + >( + value1: R1, + value2: R2, + value3: R3, + ): ExpressionWrapper> + + refTuple< + R1 extends ReferenceExpression, + R2 extends ReferenceExpression, + R3 extends ReferenceExpression, + R4 extends ReferenceExpression, + >( + value1: R1, + value2: R2, + value3: R3, + value4: R4, + ): ExpressionWrapper> + + refTuple< + R1 extends ReferenceExpression, + R2 extends ReferenceExpression, + R3 extends ReferenceExpression, + R4 extends ReferenceExpression, + R5 extends ReferenceExpression, + >( + value1: R1, + value2: R2, + value3: R3, + value4: R4, + value5: R5, + ): ExpressionWrapper> /** - * Creates a binary expression. - * - * See {@link cmpr} for creating binary comparison operations. + * Creates a value tuple expression. * - * This function returns an {@link Expression} and can be used pretty much anywhere. - * See the examples for a couple of possible use cases. + * This creates a tuple using values by default. See {@link refTuple} if you need to create + * tuples using column references. * * ### Examples * - * In the following example `bxp` is used to increment an integer column: - * * ```ts - * db.updateTable('person') - * .set((eb) => ({ - * age: eb.bxp('age', '+', 1) - * })) - * .where('id', '=', id) + * db.selectFrom('person') + * .selectAll('person') + * .where(({ eb, refTuple, tuple }) => eb( + * refTuple('first_name', 'last_name'), + * 'in', + * [ + * tuple('Jennifer', 'Aniston'), + * tuple('Sylvester', 'Stallone') + * ] + * )) * ``` * * The generated SQL (PostgreSQL): * * ```sql - * update "person" - * set "age" = "age" + $1 - * where "id" = $2 + * select + * "person".* + * from + * "person" + * where + * ("first_name", "last_name") + * in + * ( + * ($1, $2), + * ($3, $4) + * ) * ``` + */ + tuple( + value1: V1, + value2: V2, + ): ExpressionWrapper> + + tuple( + value1: V1, + value2: V2, + value3: V3, + ): ExpressionWrapper> + + tuple( + value1: V1, + value2: V2, + value3: V3, + value4: V4, + ): ExpressionWrapper> + + tuple( + value1: V1, + value2: V2, + value3: V3, + value4: V4, + value5: V5, + ): ExpressionWrapper> + + /** + * Returns a literal value expression. * - * By default the third argument is a value. {@link ref} can be used to - * pass in a column reference instead: + * 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 - * db.updateTable('person') - * .set((eb) => ({ - * age: eb.bxp('age', '+', eb.ref('age')) - * })) - * .where('id', '=', id) + * db.selectFrom('person') + * .select((eb) => eb.lit(1).as('one')) * ``` * * The generated SQL (PostgreSQL): * * ```sql - * update "person" - * set "age" = "age" + "age" - * where "id" = $1 + * select 1 as "one" from "person" * ``` */ - bxp< - RE extends ReferenceExpression, - OP extends BinaryOperatorExpression - >( - lhs: RE, - op: OP, - rhs: OperandValueExpression - ): ExpressionWrapper< - OP extends ComparisonOperator - ? SqlBool - : ExtractTypeFromReferenceExpression - > + lit( + literal: VE, + ): ExpressionWrapper /** * Creates an unary expression. @@ -436,8 +765,8 @@ export interface ExpressionBuilder { */ unary>( op: UnaryOperator, - expr: RE - ): ExpressionWrapper> + expr: RE, + ): ExpressionWrapper> /** * Creates a `not` operation. @@ -447,8 +776,8 @@ export interface ExpressionBuilder { * @see {@link unary} */ not>( - expr: RE - ): ExpressionWrapper> + expr: RE, + ): ExpressionWrapper> /** * Creates an `exists` operation. @@ -458,8 +787,8 @@ export interface ExpressionBuilder { * @see {@link unary} */ exists>( - expr: RE - ): ExpressionWrapper + expr: RE, + ): ExpressionWrapper /** * Creates a negation operation. @@ -469,27 +798,83 @@ export interface ExpressionBuilder { * @see {@link unary} */ neg>( - expr: RE - ): ExpressionWrapper> + expr: RE, + ): ExpressionWrapper> + + /** + * Creates a `between` expression. + * + * ### Examples + * + * ```ts + * db.selectFrom('person') + * .selectAll() + * .where((eb) => eb.between('age', 40, 60)) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * select * from "person" where "age" between $1 and $2 + * ``` + */ + between< + RE extends ReferenceExpression, + SE extends OperandValueExpression, + EE extends OperandValueExpression, + >( + expr: RE, + start: SE, + end: EE, + ): ExpressionWrapper + + /** + * Creates a `between symmetric` expression. + * + * ### Examples + * + * ```ts + * db.selectFrom('person') + * .selectAll() + * .where((eb) => eb.betweenSymmetric('age', 40, 60)) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * select * from "person" where "age" between symmetric $1 and $2 + * ``` + */ + betweenSymmetric< + RE extends ReferenceExpression, + SE extends OperandValueExpression, + EE extends OperandValueExpression, + >( + expr: RE, + start: SE, + end: EE, + ): ExpressionWrapper /** * 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` with {@link cmpr} to create a `WHERE expr1 AND expr2 AND expr3` + * In this example we use `and` to create a `WHERE expr1 AND expr2 AND expr3` * statement: * * ```ts * db.selectFrom('person') * .selectAll('person') - * .where(({ and, cmpr }) => and([ - * cmpr('first_name', '=', 'Jennifer'), - * cmpr('fist_name', '=', 'Arnold'), - * cmpr('fist_name', '=', 'Sylvester') + * .where((eb) => eb.and([ + * eb('first_name', '=', 'Jennifer'), + * eb('fist_name', '=', 'Arnold'), + * eb('fist_name', '=', 'Sylvester') * ])) * ``` * @@ -498,31 +883,64 @@ export interface ExpressionBuilder { * ```sql * select "person".* * from "person" - * where "first_name" = $1 - * and "first_name" = $2 - * and "first_name" = $3 + * 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 + * db.selectFrom('person') + * .selectAll('person') + * .where((eb) => eb.and({ + * first_name: 'Jennifer', + * last_name: 'Aniston' + * })) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * select "person".* + * from "person" + * where ( + * "first_name" = $1 + * and "last_name" = $2 + * ) * ``` */ - and(expres: ReadonlyArray>): ExpressionWrapper + and>( + exprs: ReadonlyArray, + ): ExpressionWrapper + + and>>( + exprs: E, + ): ExpressionWrapper /** * 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` with {@link cmpr} to create a `WHERE expr1 OR expr2 OR expr3` + * In this example we use `or` to create a `WHERE expr1 OR expr2 OR expr3` * statement: * * ```ts * db.selectFrom('person') * .selectAll('person') - * .where(({ or, cmpr }) => or([ - * cmpr('first_name', '=', 'Jennifer'), - * cmpr('fist_name', '=', 'Arnold'), - * cmpr('fist_name', '=', 'Sylvester') + * .where((eb) => eb.or([ + * eb('first_name', '=', 'Jennifer'), + * eb('fist_name', '=', 'Arnold'), + * eb('fist_name', '=', 'Sylvester') * ])) * ``` * @@ -531,12 +949,129 @@ export interface ExpressionBuilder { * ```sql * select "person".* * from "person" - * where "first_name" = $1 - * or "first_name" = $2 - * or "first_name" = $3 + * 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 + * db.selectFrom('person') + * .selectAll('person') + * .where((eb) => eb.or({ + * first_name: 'Jennifer', + * last_name: 'Aniston' + * })) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * select "person".* + * from "person" + * where ( + * "first_name" = $1 + * or "last_name" = $2 + * ) * ``` */ - or(expres: ReadonlyArray>): ExpressionWrapper + or>( + exprs: ReadonlyArray, + ): ExpressionWrapper + + or>>( + exprs: E, + ): ExpressionWrapper + + /** + * Wraps the expression in parentheses. + * + * ### Examples + * + * ```ts + * db.selectFrom('person') + * .selectAll('person') + * .where((eb) => eb(eb.parens('age', '+', 1), '/', 100), '<', 0.1)) + * ``` + * + * 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 + * db.selectFrom('person') + * .selectAll('person') + * .where((eb) => eb.parens( + * eb('age', '=', 1).or('age', '=', 2)) + * ).and( + * eb('first_name', '=', 'Jennifer').or('first_name', '=', 'Arnold') + * )) + * ``` + * + * 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, + OP extends BinaryOperatorExpression, + VE extends OperandValueExpressionOrList, + >( + lhs: RE, + op: OP, + rhs: VE, + ): ExpressionWrapper< + DB, + TB, + OP extends ComparisonOperator + ? SqlBool + : ExtractTypeFromReferenceExpression + > + + parens(expr: Expression): ExpressionWrapper + + /** + * 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 + * db.selectFrom('person') + * .select((eb) => [ + * 'id', + * 'first_name', + * eb.cast('age', 'integer').as('age') + * ]) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * select cast("age" as integer) as "age" + * from "person" + * ``` + */ + cast = ReferenceExpression>( + expr: RE, + dataType: DataTypeExpression, + ): ExpressionWrapper /** * See {@link QueryCreator.withSchema} @@ -547,146 +1082,233 @@ export interface ExpressionBuilder { } export function createExpressionBuilder( - executor: QueryExecutor = NOOP_QUERY_EXECUTOR + executor: QueryExecutor = NOOP_QUERY_EXECUTOR, ): ExpressionBuilder { + function binary< + RE extends ReferenceExpression, + OP extends BinaryOperatorExpression, + >( + lhs: RE, + op: OP, + rhs: OperandValueExpressionOrList, + ): ExpressionWrapper< + DB, + TB, + OP extends ComparisonOperator + ? SqlBool + : ExtractTypeFromReferenceExpression + > { + return new ExpressionWrapper(parseValueBinaryOperation(lhs, op, rhs)) + } + function unary>( op: UnaryOperator, - expr: RE - ): ExpressionWrapper> { + expr: RE, + ): ExpressionWrapper> { return new ExpressionWrapper(parseUnaryOperation(op, expr)) } - return { - get fn(): FunctionModule { - return createFunctionModule() - }, + const eb = Object.assign(binary, { + fn: undefined! as FunctionModule, + eb: undefined! as ExpressionBuilder, selectFrom(table: TableExpressionOrList): any { - return new SelectQueryBuilder({ + return createSelectQueryBuilder({ queryId: createQueryId(), - executor: executor, - queryNode: SelectQueryNode.create(parseTableExpressionOrList(table)), + executor, + queryNode: SelectQueryNode.createFrom( + parseTableExpressionOrList(table), + ), }) }, case>( - reference?: RE + reference?: RE, ): CaseBuilder> { return new CaseBuilder({ node: CaseNode.create( isUndefined(reference) ? undefined - : parseReferenceExpression(reference) + : parseReferenceExpression(reference), ), }) }, ref>( - reference: RE - ): ExpressionWrapper> { - return new ExpressionWrapper(parseStringReference(reference)) + reference: RE, + op?: JSONOperatorWith$, + ): any { + if (isUndefined(op)) { + return new ExpressionWrapper(parseStringReference(reference)) + } + + return new JSONPathBuilder(parseJSONReference(reference, op)) + }, + + jsonPath< + $ extends StringReference = never, + >(): IsNever<$> extends true + ? KyselyTypeError<"You must provide a column reference as this method's $ generic"> + : JSONPathBuilder> { + return new JSONPathBuilder(JSONPathNode.create()) as any + }, + + table( + table: T, + ): ExpressionWrapper> { + return new ExpressionWrapper(parseTable(table)) }, val( - value: VE - ): ExpressionWrapper> { - return new ExpressionWrapper(parseValueExpressionOrList(value)) + value: VE, + ): ExpressionWrapper> { + return new ExpressionWrapper(parseValueExpression(value)) }, - cmpr< - O extends SqlBool = SqlBool, - RE extends ReferenceExpression = ReferenceExpression - >( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): ExpressionWrapper { - return new ExpressionWrapper(parseValueBinaryOperation(lhs, op, rhs)) + refTuple( + ...values: ReadonlyArray> + ): ExpressionWrapper { + return new ExpressionWrapper( + TupleNode.create(values.map(parseReferenceExpression)), + ) }, - bxp< - RE extends ReferenceExpression, - OP extends BinaryOperatorExpression - >( - lhs: RE, - op: OP, - rhs: OperandValueExpression - ): ExpressionWrapper< - OP extends ComparisonOperator - ? SqlBool - : ExtractTypeFromReferenceExpression - > { - return new ExpressionWrapper(parseValueBinaryOperation(lhs, op, rhs)) + tuple(...values: ReadonlyArray): ExpressionWrapper { + return new ExpressionWrapper( + TupleNode.create(values.map(parseValueExpression)), + ) + }, + + lit( + value: VE, + ): ExpressionWrapper { + return new ExpressionWrapper(parseSafeImmediateValue(value)) }, unary, not>( - expr: RE - ): ExpressionWrapper> { + expr: RE, + ): ExpressionWrapper< + DB, + TB, + ExtractTypeFromReferenceExpression + > { return unary('not', expr) }, exists>( - expr: RE - ): ExpressionWrapper { + expr: RE, + ): ExpressionWrapper { return unary('exists', expr) }, neg>( - expr: RE - ): ExpressionWrapper> { + expr: RE, + ): ExpressionWrapper< + DB, + TB, + ExtractTypeFromReferenceExpression + > { return unary('-', expr) }, - and(exprs: ReadonlyArray>): ExpressionWrapper { - if (exprs.length === 0) { - return new ExpressionWrapper(ValueNode.createImmediate(true)) - } else if (exprs.length === 1) { - return new ExpressionWrapper(exprs[0].toOperationNode()) - } + between>( + expr: RE, + start: OperandValueExpression, + end: OperandValueExpression, + ): ExpressionWrapper { + return new ExpressionWrapper( + BinaryOperationNode.create( + parseReferenceExpression(expr), + OperatorNode.create('between'), + AndNode.create( + parseValueExpression(start), + parseValueExpression(end), + ), + ), + ) + }, - let node = AndNode.create( - exprs[0].toOperationNode(), - exprs[1].toOperationNode() + betweenSymmetric>( + expr: RE, + start: OperandValueExpression, + end: OperandValueExpression, + ): ExpressionWrapper { + return new ExpressionWrapper( + BinaryOperationNode.create( + parseReferenceExpression(expr), + OperatorNode.create('between symmetric'), + AndNode.create( + parseValueExpression(start), + parseValueExpression(end), + ), + ), ) + }, - for (let i = 2; i < exprs.length; ++i) { - node = AndNode.create(node, exprs[i].toOperationNode()) + and( + exprs: + | ReadonlyArray> + | Readonly>, + ): ExpressionWrapper { + if (isReadonlyArray(exprs)) { + return new ExpressionWrapper(parseFilterList(exprs, 'and')) } - return new ExpressionWrapper(ParensNode.create(node)) + return new ExpressionWrapper(parseFilterObject(exprs, 'and')) }, - or(exprs: ReadonlyArray>): ExpressionWrapper { - if (exprs.length === 0) { - return new ExpressionWrapper(ValueNode.createImmediate(false)) - } else if (exprs.length === 1) { - return new ExpressionWrapper(exprs[0].toOperationNode()) + or( + exprs: + | ReadonlyArray> + | Readonly>, + ): ExpressionWrapper { + if (isReadonlyArray(exprs)) { + return new ExpressionWrapper(parseFilterList(exprs, 'or')) } - let node = OrNode.create( - exprs[0].toOperationNode(), - exprs[1].toOperationNode() - ) + return new ExpressionWrapper(parseFilterObject(exprs, 'or')) + }, + + parens(...args: any[]) { + const node = parseValueBinaryOperationOrExpression(args) - for (let i = 2; i < exprs.length; ++i) { - node = OrNode.create(node, exprs[i].toOperationNode()) + if (ParensNode.is(node)) { + // No double wrapping. + return new ExpressionWrapper(node) + } else { + return new ExpressionWrapper(ParensNode.create(node)) } + }, - return new ExpressionWrapper(ParensNode.create(node)) + cast>( + expr: RE, + dataType: DataTypeExpression, + ) { + return new ExpressionWrapper( + CastNode.create( + parseReferenceExpression(expr), + parseDataTypeExpression(dataType), + ), + ) }, withSchema(schema: string): ExpressionBuilder { return createExpressionBuilder( - executor.withPluginAtFront(new WithSchemaPlugin(schema)) + executor.withPluginAtFront(new WithSchemaPlugin(schema)), ) }, - } + }) + + eb.fn = createFunctionModule() + eb.eb = eb + + return eb } export function expressionBuilder( - _: SelectQueryBuilder + _: SelectQueryBuilder, ): ExpressionBuilder export function expressionBuilder(): ExpressionBuilder< @@ -695,7 +1317,7 @@ export function expressionBuilder(): ExpressionBuilder< > export function expressionBuilder( - _?: unknown + _?: unknown, ): ExpressionBuilder { return createExpressionBuilder() } diff --git a/src/expression/expression-wrapper.ts b/src/expression/expression-wrapper.ts index e9818048b..33d0cdc47 100644 --- a/src/expression/expression-wrapper.ts +++ b/src/expression/expression-wrapper.ts @@ -1,10 +1,28 @@ 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 { OperationNode } from '../operation-node/operation-node.js' -import { AliasedExpression, Expression } from './expression.js' +import { OrNode } from '../operation-node/or-node.js' +import { ParensNode } from '../operation-node/parens-node.js' +import { + ComparisonOperatorExpression, + OperandValueExpressionOrList, + parseValueBinaryOperationOrExpression, +} from '../parser/binary-operation-parser.js' +import { OperandExpression } from '../parser/expression-parser.js' +import { ReferenceExpression } from '../parser/reference-parser.js' +import { KyselyTypeError } from '../util/type-error.js' +import { SqlBool } from '../util/type-utils.js' +import { + AliasableExpression, + AliasedExpression, + Expression, +} from './expression.js' -export class ExpressionWrapper implements Expression { +export class ExpressionWrapper + implements AliasableExpression +{ readonly #node: OperationNode constructor(node: OperationNode) { @@ -25,8 +43,8 @@ export class ExpressionWrapper implements Expression { * ```ts * const result = await db * .selectFrom('person') - * .select(eb => - * eb.cmpr('first_name', '=', 'Jennifer').as('is_jennifer') + * .select((eb) => + * eb('first_name', '=', 'Jennifer').as('is_jennifer') * ) * .executeTakeFirstOrThrow() * @@ -42,18 +60,199 @@ export class ExpressionWrapper implements Expression { * ``` */ as(alias: A): AliasedExpression + as(alias: Expression): AliasedExpression + as(alias: string | Expression): AliasedExpression { return new AliasedExpressionWrapper(this, alias) } /** - * Change the output type of the raw expression. + * Combines `this` and another expression using `OR`. + * + * Also see {@link ExpressionBuilder.or} + * + * ### Examples + * + * ```ts + * db.selectFrom('person') + * .selectAll() + * .where(eb => eb('first_name', '=', 'Jennifer') + * .or('first_name', '=', 'Arnold') + * .or('first_name', '=', 'Sylvester') + * ) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```ts + * 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 + * 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') + * ) + * ) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```ts + * 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, + VE extends OperandValueExpressionOrList, + >( + lhs: RE, + op: ComparisonOperatorExpression, + rhs: VE, + ): T extends SqlBool + ? OrWrapper + : KyselyTypeError<'or() method can only be called on boolean expressions'> + + or>( + expression: E, + ): T extends SqlBool + ? OrWrapper + : KyselyTypeError<'or() method can only be called on boolean expressions'> + + or(...args: any[]): any { + return new OrWrapper( + OrNode.create(this.#node, parseValueBinaryOperationOrExpression(args)), + ) + } + + /** + * Combines `this` and another expression using `AND`. + * + * Also see {@link ExpressionBuilder.and} + * + * ### Examples + * + * ```ts + * db.selectFrom('person') + * .selectAll() + * .where(eb => eb('first_name', '=', 'Jennifer') + * .and('last_name', '=', 'Aniston') + * .and('age', '>', 40) + * ) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```ts + * 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 + * 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') + * ) + * ) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```ts + * 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, + VE extends OperandValueExpressionOrList, + >( + lhs: RE, + op: ComparisonOperatorExpression, + rhs: VE, + ): T extends SqlBool + ? AndWrapper + : KyselyTypeError<'and() method can only be called on boolean expressions'> + + and>( + expression: E, + ): T extends SqlBool + ? AndWrapper + : KyselyTypeError<'and() method can only be called on boolean expressions'> + + and(...args: any[]): any { + 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(): ExpressionWrapper { + $castTo(): ExpressionWrapper { + 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(): ExpressionWrapper> { return new ExpressionWrapper(this.#node) } @@ -88,7 +287,173 @@ export class AliasedExpressionWrapper this.#expr.toOperationNode(), isOperationNodeSource(this.#alias) ? this.#alias.toOperationNode() - : IdentifierNode.create(this.#alias) + : IdentifierNode.create(this.#alias), + ) + } +} + +export class OrWrapper + implements AliasableExpression +{ + readonly #node: OrNode + + constructor(node: OrNode) { + this.#node = node + } + + /** @private */ + get expressionType(): T | undefined { + return 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): + * + * ```ts + * select "first_name" = $1 or "first_name" = $2 as "is_jennifer_or_sylvester" + * from "person" + * ``` + */ + as(alias: A): AliasedExpression + + as(alias: Expression): AliasedExpression + + as(alias: string | Expression): AliasedExpression { + return new AliasedExpressionWrapper(this, alias) + } + + /** + * Combines `this` and another expression using `OR`. + * + * See {@link ExpressionWrapper.or} for examples. + */ + or< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >(lhs: RE, op: ComparisonOperatorExpression, rhs: VE): OrWrapper + + or>(expression: E): OrWrapper + + or(...args: any[]): any { + 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(): OrWrapper { + return new OrWrapper(this.#node) + } + + toOperationNode(): ParensNode { + return ParensNode.create(this.#node) + } +} + +export class AndWrapper + implements AliasableExpression +{ + readonly #node: AndNode + + constructor(node: AndNode) { + this.#node = node + } + + /** @private */ + get expressionType(): T | undefined { + return 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_or_sylvester) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```ts + * select "first_name" = $1 and "first_name" = $2 as "is_jennifer_aniston" + * from "person" + * ``` + */ + as(alias: A): AliasedExpression + + as(alias: Expression): AliasedExpression + + as(alias: string | Expression): AliasedExpression { + return new AliasedExpressionWrapper(this, alias) + } + + /** + * Combines `this` and another expression using `AND`. + * + * See {@link ExpressionWrapper.and} for examples. + */ + and< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >(lhs: RE, op: ComparisonOperatorExpression, rhs: VE): AndWrapper + + and>( + expression: E, + ): AndWrapper + + and(...args: any[]): any { + 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(): AndWrapper { + return new AndWrapper(this.#node) + } + + toOperationNode(): ParensNode { + return ParensNode.create(this.#node) + } } diff --git a/src/expression/expression.ts b/src/expression/expression.ts index fd60d83c5..f4964e5ee 100644 --- a/src/expression/expression.ts +++ b/src/expression/expression.ts @@ -56,7 +56,71 @@ export interface Expression extends OperationNodeSource { } /** - * Just like `Expression` but also holds an alias type `A`. + * An expression with an `as` method. + */ +export interface AliasableExpression extends Expression { + /** + * Returns an aliased version of the expression. + * + * 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` returns an AliasableExpression + * eb.fn('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): + * + * ```ts + * 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 + * 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']) + * ) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```ts + * insert into "person" ("first_name", "last_name") + * from (values (1, 'foo')) as t(a, b) + * select "t"."a", "t"."b" + * ``` + */ + as(alias: A): AliasedExpression + as(alias: Expression): AliasedExpression +} + +/** + * A type that holds an expression and an alias for it. * * `AliasedExpression` 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 @@ -112,7 +176,7 @@ export function isExpression(obj: unknown): obj is Expression { } export function isAliasedExpression( - obj: unknown + obj: unknown, ): obj is AliasedExpression { return ( isObject(obj) && diff --git a/src/helpers/mssql.ts b/src/helpers/mssql.ts new file mode 100644 index 000000000..982e6dfa0 --- /dev/null +++ b/src/helpers/mssql.ts @@ -0,0 +1,173 @@ +import { Expression } from '../expression/expression.js' +import { RawBuilder } from '../raw-builder/raw-builder.js' +import { sql } from '../raw-builder/sql.js' +import { Simplify } from '../util/type-utils.js' + +/** + * An MS SQL Server helper for aggregating a subquery into a JSON array. + * + * NOTE: This helper only works correctly if you've installed the `ParseJSONResultsPlugin`. + * Otherwise the nested selections will be returned as JSON strings. + * + * The plugin can be installed like this: + * + * ```ts + * const db = new Kysely({ + * dialect: new MssqlDialect(config), + * plugins: [new ParseJSONResultsPlugin()] + * }) + * ``` + * + * ### Examples + * + * ```ts + * const result = await db + * .selectFrom('person') + * .select((eb) => [ + * 'id', + * jsonArrayFrom( + * eb.selectFrom('pet') + * .select(['pet.id as pet_id', 'pet.name']) + * .whereRef('pet.owner_id', '=', 'person.id') + * .orderBy('pet.name') + * .modifyEnd(sql`offset 0 rows`) + * ).as('pets') + * ]) + * .execute() + * + * result[0].id + * result[0].pets[0].pet_id + * result[0].pets[0].name + * ``` + * + * The generated SQL (MS SQL Server): + * + * ```sql + * select "id", ( + * select coalesce((select * from ( + * select "pet"."id" as "pet_id", "pet"."name" + * from "pet" + * where "pet"."owner_id" = "person"."id" + * order by "pet"."name" + * offset 0 rows + * ) as "agg" for json path, include_null_values), '[]') + * ) as "pets" + * from "person" + * ``` + */ +export function jsonArrayFrom( + expr: Expression, +): RawBuilder[]> { + return sql`coalesce((select * from ${expr} as agg for json path, include_null_values), '[]')` +} + +/** + * An MS SQL Server helper for turning a subquery into a JSON object. + * + * The subquery must only return one row. + * + * NOTE: This helper only works correctly if you've installed the `ParseJSONResultsPlugin`. + * Otherwise the nested selections will be returned as JSON strings. + * + * The plugin can be installed like this: + * + * ```ts + * const db = new Kysely({ + * dialect: new MssqlDialect(config), + * plugins: [new ParseJSONResultsPlugin()] + * }) + * ``` + * + * ### Examples + * + * ```ts + * const result = await db + * .selectFrom('person') + * .select((eb) => [ + * 'id', + * jsonObjectFrom( + * eb.selectFrom('pet') + * .select(['pet.id as pet_id', 'pet.name']) + * .whereRef('pet.owner_id', '=', 'person.id') + * .where('pet.is_favorite', '=', 1) + * ).as('favorite_pet') + * ]) + * .execute() + * + * result[0].id + * result[0].favorite_pet.pet_id + * result[0].favorite_pet.name + * ``` + * + * The generated SQL (MS SQL Server): + * + * ```sql + * select "id", ( + * select * from ( + * select "pet"."id" as "pet_id", "pet"."name" + * from "pet" + * where "pet"."owner_id" = "person"."id" + * and "pet"."is_favorite" = @1 + * ) as "agg" for json path, include_null_values, without_array_wrapper + * ) as "favorite_pet" + * from "person" + * ``` + */ +export function jsonObjectFrom( + expr: Expression, +): RawBuilder | null> { + return sql`(select * from ${expr} as agg for json path, include_null_values, without_array_wrapper)` +} + +/** + * The MS SQL Server `json_query` function, single argument variant. + * + * NOTE: This helper only works correctly if you've installed the `ParseJSONResultsPlugin`. + * Otherwise the nested selections will be returned as JSON strings. + * + * The plugin can be installed like this: + * + * ```ts + * const db = new Kysely({ + * dialect: new MssqlDialect(config), + * plugins: [new ParseJSONResultsPlugin()] + * }) + * ``` + * + * ### Examples + * + * ```ts + * const result = await db + * .selectFrom('person') + * .select((eb) => [ + * 'id', + * jsonBuildObject({ + * first: eb.ref('first_name'), + * last: eb.ref('last_name'), + * full: eb.fn('concat', ['first_name', eb.val(' '), 'last_name']) + * }).as('name') + * ]) + * .execute() + * ``` + * + * The generated SQL (MS SQL Server): + * + * ```sql + * select "id", json_query( + * '{"first":"'+"first_name"+',"last":"'+"last_name"+',"full":"'+concat("first_name", ' ', "last_name")+'"}' + * ) as "name" + * from "person" + * ``` + */ +export function jsonBuildObject>>( + obj: O, +): RawBuilder< + Simplify<{ + [K in keyof O]: O[K] extends Expression ? V : never + }> +> { + return sql`json_query('{${sql.join( + Object.keys(obj).map((k) => sql`"${sql.raw(k)}":"'+${obj[k]}+'"`), + sql`,`, + )}}')` +} diff --git a/src/helpers/mysql.ts b/src/helpers/mysql.ts index 0b38b4496..ebe7f8508 100644 --- a/src/helpers/mysql.ts +++ b/src/helpers/mysql.ts @@ -1,20 +1,18 @@ import { Expression } from '../expression/expression.js' -import { AliasNode } from '../operation-node/alias-node.js' -import { ColumnNode } from '../operation-node/column-node.js' -import { IdentifierNode } from '../operation-node/identifier-node.js' -import { ReferenceNode } from '../operation-node/reference-node.js' import { SelectQueryNode } from '../operation-node/select-query-node.js' -import { SelectQueryBuilder } from '../query-builder/select-query-builder.js' +import { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js' import { RawBuilder } from '../raw-builder/raw-builder.js' import { sql } from '../raw-builder/sql.js' +import { getJsonObjectArgs } from '../util/json-object-args.js' import { Simplify } from '../util/type-utils.js' /** * A MySQL helper for aggregating a subquery into a JSON array. * * NOTE: This helper is only guaranteed to fully work with the built-in `MysqlDialect`. - * While the produced SQL is compatibe with all MySQL databases, some 3rd party dialects - * may not parse the nested results into arrays. + * While the produced SQL is compatible with all MySQL databases, some 3rd party dialects + * may not parse the nested JSON into arrays. In these cases you can use the built in + * `ParseJSONResultsPlugin` to parse the results. * * ### Examples * @@ -26,7 +24,7 @@ import { Simplify } from '../util/type-utils.js' * jsonArrayFrom( * eb.selectFrom('pet') * .select(['pet.id as pet_id', 'pet.name']) - * .where('pet.owner_id', '=', 'person.id') + * .whereRef('pet.owner_id', '=', 'person.id') * .orderBy('pet.name') * ).as('pets') * ]) @@ -55,10 +53,10 @@ import { Simplify } from '../util/type-utils.js' * ``` */ export function jsonArrayFrom( - expr: SelectQueryBuilder + expr: SelectQueryBuilderExpression, ): RawBuilder[]> { return sql`(select cast(coalesce(json_arrayagg(json_object(${sql.join( - getJsonObjectArgs(expr.toOperationNode(), 'agg') + getMysqlJsonObjectArgs(expr.toOperationNode(), 'agg'), )})), '[]') as json) from ${expr} as agg)` } @@ -68,8 +66,9 @@ export function jsonArrayFrom( * The subquery must only return one row. * * NOTE: This helper is only guaranteed to fully work with the built-in `MysqlDialect`. - * While the produced SQL is compatibe with all MySQL databases, some 3rd party dialects - * may not parse the nested results into objects. + * While the produced SQL is compatible with all MySQL databases, some 3rd party dialects + * may not parse the nested JSON into objects. In these cases you can use the built in + * `ParseJSONResultsPlugin` to parse the results. * * ### Examples * @@ -81,7 +80,7 @@ export function jsonArrayFrom( * jsonObjectFrom( * eb.selectFrom('pet') * .select(['pet.id as pet_id', 'pet.name']) - * .where('pet.owner_id', '=', 'person.id') + * .whereRef('pet.owner_id', '=', 'person.id') * .where('pet.is_favorite', '=', true) * ).as('favorite_pet') * ]) @@ -110,10 +109,10 @@ export function jsonArrayFrom( * ``` */ export function jsonObjectFrom( - expr: SelectQueryBuilder + expr: SelectQueryBuilderExpression, ): RawBuilder | null> { return sql`(select json_object(${sql.join( - getJsonObjectArgs(expr.toOperationNode(), 'obj') + getMysqlJsonObjectArgs(expr.toOperationNode(), 'obj'), )}) from ${expr} as obj)` } @@ -121,8 +120,9 @@ export function jsonObjectFrom( * The MySQL `json_object` function. * * NOTE: This helper is only guaranteed to fully work with the built-in `MysqlDialect`. - * While the produced SQL is compatibe with all MySQL databases, some 3rd party dialects - * may not parse the nested results into objects. + * While the produced SQL is compatible with all MySQL databases, some 3rd party dialects + * may not parse the nested JSON into objects. In these cases you can use the built in + * `ParseJSONResultsPlugin` to parse the results. * * ### Examples * @@ -157,35 +157,26 @@ export function jsonObjectFrom( * ``` */ export function jsonBuildObject>>( - obj: O + obj: O, ): RawBuilder< Simplify<{ [K in keyof O]: O[K] extends Expression ? V : never }> > { return sql`json_object(${sql.join( - Object.keys(obj).flatMap((k) => [sql.lit(k), obj[k]]) + Object.keys(obj).flatMap((k) => [sql.lit(k), obj[k]]), )})` } -function getJsonObjectArgs( +function getMysqlJsonObjectArgs( node: SelectQueryNode, - table: string -): RawBuilder[] { - return node.selections!.flatMap(({ selection: s }) => { - if (ReferenceNode.is(s) && ColumnNode.is(s.column)) { - return [ - sql.lit(s.column.column.name), - sql.id(table, s.column.column.name), - ] - } else if (ColumnNode.is(s)) { - return [sql.lit(s.column.name), sql.id(table, s.column.name)] - } else if (AliasNode.is(s) && IdentifierNode.is(s.alias)) { - return [sql.lit(s.alias.name), sql.id(table, s.alias.name)] - } else { - throw new Error( - 'MySQL jsonArrayFrom and jsonObjectFrom functions can only handle explicit selections due to limitations of the json_object function. selectAll() is not allowed in the subquery.' - ) - } - }) + table: string, +): Expression[] { + try { + return getJsonObjectArgs(node, table) + } catch { + throw new Error( + 'MySQL jsonArrayFrom and jsonObjectFrom functions can only handle explicit selections due to limitations of the json_object function. selectAll() is not allowed in the subquery.', + ) + } } diff --git a/src/helpers/postgres.ts b/src/helpers/postgres.ts index 163c1335c..d74a50531 100644 --- a/src/helpers/postgres.ts +++ b/src/helpers/postgres.ts @@ -18,7 +18,8 @@ import { Simplify } from '../util/type-utils.js' * `jsonArrayFrom`, are not guaranteed to work with third party dialects. In order for * them to work, the dialect must automatically parse the `json` data type into * javascript JSON values like objects and arrays. Some dialects might simply return - * the data as a JSON string. + * the data as a JSON string. In these cases you can use the built in `ParseJSONResultsPlugin` + * to parse the results. * * ```ts * import { jsonArrayFrom } from 'kysely/helpers/postgres' @@ -52,7 +53,7 @@ import { Simplify } from '../util/type-utils.js' * ``` */ export function jsonArrayFrom( - expr: Expression + expr: Expression, ): RawBuilder[]> { return sql`(select coalesce(json_agg(agg), '[]') from ${expr} as agg)` } @@ -71,10 +72,11 @@ export function jsonArrayFrom( * use the `jsonObjectFrom` helper to fetch person's favorite pet along with the person's id. * * Please keep in mind that the helpers under the `kysely/helpers` folder, including - * `jsonObjectFrom`, are not guaranteed to work with third party dialects. In order for + * `jsonObjectFrom`, are not guaranteed to work with 3rd party dialects. In order for * them to work, the dialect must automatically parse the `json` data type into * javascript JSON values like objects and arrays. Some dialects might simply return - * the data as a JSON string. + * the data as a JSON string. In these cases you can use the built in `ParseJSONResultsPlugin` + * to parse the results. * * ```ts * import { jsonObjectFrom } from 'kysely/helpers/postgres' @@ -108,7 +110,7 @@ export function jsonArrayFrom( * ``` */ export function jsonObjectFrom( - expr: Expression + expr: Expression, ): RawBuilder | null> { return sql`(select to_json(obj) from ${expr} as obj)` } @@ -117,8 +119,9 @@ export function jsonObjectFrom( * The PostgreSQL `json_build_object` function. * * NOTE: This helper is only guaranteed to fully work with the built-in `PostgresDialect`. - * While the produced SQL is compatibe with all PostgreSQL databases, some 3rd party dialects - * may not parse the nested results into objects. + * While the produced SQL is compatible with all PostgreSQL databases, some 3rd party dialects + * may not parse the nested JSON into objects. In these cases you can use the built in + * `ParseJSONResultsPlugin` to parse the results. * * ### Examples * @@ -153,13 +156,13 @@ export function jsonObjectFrom( * ``` */ export function jsonBuildObject>>( - obj: O + obj: O, ): RawBuilder< Simplify<{ [K in keyof O]: O[K] extends Expression ? V : never }> > { return sql`json_build_object(${sql.join( - Object.keys(obj).flatMap((k) => [sql.lit(k), obj[k]]) + Object.keys(obj).flatMap((k) => [sql.lit(k), obj[k]]), )})` } diff --git a/src/helpers/sqlite.ts b/src/helpers/sqlite.ts new file mode 100644 index 000000000..91b5af6ad --- /dev/null +++ b/src/helpers/sqlite.ts @@ -0,0 +1,203 @@ +import { Expression } from '../expression/expression.js' +import { SelectQueryNode } from '../operation-node/select-query-node.js' +import { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js' +import { RawBuilder } from '../raw-builder/raw-builder.js' +import { sql } from '../raw-builder/sql.js' +import { getJsonObjectArgs } from '../util/json-object-args.js' +import { Simplify } from '../util/type-utils.js' + +/** + * A SQLite helper for aggregating a subquery into a JSON array. + * + * NOTE: This helper only works correctly if you've installed the `ParseJSONResultsPlugin`. + * Otherwise the nested selections will be returned as JSON strings. + * + * The plugin can be installed like this: + * + * ```ts + * const db = new Kysely({ + * dialect: new SqliteDialect(config), + * plugins: [new ParseJSONResultsPlugin()] + * }) + * ``` + * + * ### Examples + * + * ```ts + * const result = await db + * .selectFrom('person') + * .select((eb) => [ + * 'id', + * jsonArrayFrom( + * eb.selectFrom('pet') + * .select(['pet.id as pet_id', 'pet.name']) + * .whereRef('pet.owner_id', '=', 'person.id') + * .orderBy('pet.name') + * ).as('pets') + * ]) + * .execute() + * + * result[0].id + * result[0].pets[0].pet_id + * result[0].pets[0].name + * ``` + * + * The generated SQL (SQLite): + * + * ```sql + * select "id", ( + * select coalesce(json_group_array(json_object( + * 'pet_id', "agg"."pet_id", + * 'name', "agg"."name" + * )), '[]') from ( + * select "pet"."id" as "pet_id", "pet"."name" + * from "pet" + * where "pet"."owner_id" = "person"."id" + * order by "pet"."name" + * ) as "agg" + * ) as "pets" + * from "person" + * ``` + */ +export function jsonArrayFrom( + expr: SelectQueryBuilderExpression, +): RawBuilder[]> { + return sql`(select coalesce(json_group_array(json_object(${sql.join( + getSqliteJsonObjectArgs(expr.toOperationNode(), 'agg'), + )})), '[]') from ${expr} as agg)` +} + +/** + * A SQLite helper for turning a subquery into a JSON object. + * + * The subquery must only return one row. + * + * NOTE: This helper only works correctly if you've installed the `ParseJSONResultsPlugin`. + * Otherwise the nested selections will be returned as JSON strings. + * + * The plugin can be installed like this: + * + * ```ts + * const db = new Kysely({ + * dialect: new SqliteDialect(config), + * plugins: [new ParseJSONResultsPlugin()] + * }) + * ``` + * + * ### Examples + * + * ```ts + * const result = await db + * .selectFrom('person') + * .select((eb) => [ + * 'id', + * jsonObjectFrom( + * eb.selectFrom('pet') + * .select(['pet.id as pet_id', 'pet.name']) + * .whereRef('pet.owner_id', '=', 'person.id') + * .where('pet.is_favorite', '=', true) + * ).as('favorite_pet') + * ]) + * .execute() + * + * result[0].id + * result[0].favorite_pet.pet_id + * result[0].favorite_pet.name + * ``` + * + * The generated SQL (SQLite): + * + * ```sql + * select "id", ( + * select json_object( + * 'pet_id', "obj"."pet_id", + * 'name', "obj"."name" + * ) from ( + * select "pet"."id" as "pet_id", "pet"."name" + * from "pet" + * where "pet"."owner_id" = "person"."id" + * and "pet"."is_favorite" = ? + * ) as obj + * ) as "favorite_pet" + * from "person"; + * ``` + */ +export function jsonObjectFrom( + expr: SelectQueryBuilderExpression, +): RawBuilder | null> { + return sql`(select json_object(${sql.join( + getSqliteJsonObjectArgs(expr.toOperationNode(), 'obj'), + )}) from ${expr} as obj)` +} + +/** + * The SQLite `json_object` function. + * + * NOTE: This helper only works correctly if you've installed the `ParseJSONResultsPlugin`. + * Otherwise the nested selections will be returned as JSON strings. + * + * The plugin can be installed like this: + * + * ```ts + * const db = new Kysely({ + * dialect: new SqliteDialect(config), + * plugins: [new ParseJSONResultsPlugin()] + * }) + * ``` + * + * ### Examples + * + * ```ts + * const result = await db + * .selectFrom('person') + * .select((eb) => [ + * 'id', + * jsonBuildObject({ + * first: eb.ref('first_name'), + * last: eb.ref('last_name'), + * full: sql`first_name || ' ' || last_name` + * }).as('name') + * ]) + * .execute() + * + * result[0].id + * result[0].name.first + * result[0].name.last + * result[0].name.full + * ``` + * + * The generated SQL (SQLite): + * + * ```sql + * select "id", json_object( + * 'first', first_name, + * 'last', last_name, + * 'full', "first_name" || ' ' || "last_name" + * ) as "name" + * from "person" + * ``` + */ +export function jsonBuildObject>>( + obj: O, +): RawBuilder< + Simplify<{ + [K in keyof O]: O[K] extends Expression ? V : never + }> +> { + return sql`json_object(${sql.join( + Object.keys(obj).flatMap((k) => [sql.lit(k), obj[k]]), + )})` +} + +function getSqliteJsonObjectArgs( + node: SelectQueryNode, + table: string, +): Expression[] { + try { + return getJsonObjectArgs(node, table) + } catch { + throw new Error( + 'SQLite jsonArrayFrom and jsonObjectFrom functions can only handle explicit selections due to limitations of the json_object function. selectAll() is not allowed in the subquery.', + ) + } +} diff --git a/src/index.ts b/src/index.ts index 1fa85560c..b27a601d2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,7 @@ export * from './expression/expression-wrapper.js' export * from './query-builder/where-interface.js' export * from './query-builder/returning-interface.js' +export * from './query-builder/output-interface.js' export * from './query-builder/having-interface.js' export * from './query-builder/select-query-builder.js' export * from './query-builder/insert-query-builder.js' @@ -24,6 +25,9 @@ export * from './query-builder/update-result.js' export * from './query-builder/on-conflict-builder.js' export * from './query-builder/aggregate-function-builder.js' export * from './query-builder/case-builder.js' +export * from './query-builder/json-path-builder.js' +export * from './query-builder/merge-query-builder.js' +export * from './query-builder/merge-result.js' export * from './raw-builder/raw-builder.js' export * from './raw-builder/sql.js' @@ -87,6 +91,13 @@ export * from './dialect/sqlite/sqlite-query-compiler.js' export * from './dialect/sqlite/sqlite-introspector.js' export * from './dialect/sqlite/sqlite-adapter.js' +export * from './dialect/mssql/mssql-adapter.js' +export * from './dialect/mssql/mssql-dialect-config.js' +export * from './dialect/mssql/mssql-dialect.js' +export * from './dialect/mssql/mssql-driver.js' +export * from './dialect/mssql/mssql-introspector.js' +export * from './dialect/mssql/mssql-query-compiler.js' + export * from './query-compiler/default-query-compiler.js' export * from './query-compiler/query-compiler.js' @@ -97,6 +108,7 @@ export * from './plugin/kysely-plugin.js' export * from './plugin/camel-case/camel-case-plugin.js' export * from './plugin/deduplicate-joins/deduplicate-joins-plugin.js' export * from './plugin/with-schema/with-schema-plugin.js' +export * from './plugin/parse-json-results/parse-json-results-plugin.js' export * from './operation-node/add-column-node.js' export * from './operation-node/add-constraint-node.js' @@ -183,6 +195,16 @@ export * from './operation-node/set-operation-node.js' export * from './operation-node/binary-operation-node.js' export * from './operation-node/unary-operation-node.js' export * from './operation-node/using-node.js' +export * from './operation-node/json-reference-node.js' +export * from './operation-node/json-path-leg-node.js' +export * from './operation-node/json-path-node.js' +export * from './operation-node/json-operator-chain-node.js' +export * from './operation-node/tuple-node.js' +export * from './operation-node/merge-query-node.js' +export * from './operation-node/matched-node.js' +export * from './operation-node/fetch-node.js' +export * from './operation-node/top-node.js' +export * from './operation-node/output-node.js' export * from './util/column-type.js' export * from './util/compilable.js' @@ -194,19 +216,22 @@ export { AnyAliasedColumnWithTable, AnyColumn, AnyColumnWithTable, - AnySelectQueryBuilder, Equals, UnknownRow, Simplify, SqlBool, + Nullable, + NotNull, } from './util/type-utils.js' export * from './util/infer-result.js' export { logOnce } from './util/log-once.js' export { SelectExpression, + SelectCallback, SelectArg, Selection, + CallbackSelection, } from './parser/select-parser.js' export { ReferenceExpression, @@ -221,6 +246,7 @@ export { ValueExpressionOrList, } from './parser/value-parser.js' export { + SimpleTableReference, TableExpression, TableExpressionOrList, } from './parser/table-parser.js' @@ -238,5 +264,10 @@ export { ComparisonOperatorExpression, OperandValueExpression, OperandValueExpressionOrList, + FilterObject, } from './parser/binary-operation-parser.js' export { ExistsExpression } from './parser/unary-operation-parser.js' +export { + OperandExpression, + ExpressionOrFactory, +} from './parser/expression-parser.js' diff --git a/src/kysely.ts b/src/kysely.ts index cecb38b1b..bb47fa6a5 100644 --- a/src/kysely.ts +++ b/src/kysely.ts @@ -32,6 +32,7 @@ import { CaseNode } from './operation-node/case-node.js' import { parseExpression } from './parser/expression-parser.js' import { Expression } from './expression/expression.js' import { WithSchemaPlugin } from './plugin/with-schema/with-schema-plugin.js' +import { DrainOuterGeneric } from './util/type-utils.js' /** * The main Kysely class. @@ -56,7 +57,7 @@ import { WithSchemaPlugin } from './plugin/with-schema/with-schema-plugin.js' * id: Generated * owner_id: number * name: string - * species 'cat' | 'dog' + * species: 'cat' | 'dog' * } * * interface Database { @@ -106,7 +107,7 @@ export class Kysely compiler, adapter, connectionProvider, - args.plugins ?? [] + args.plugins ?? [], ) superProps = { executor } @@ -158,7 +159,7 @@ export class Kysely case(value?: Expression): any { return new CaseBuilder({ node: CaseNode.create( - isUndefined(value) ? undefined : parseExpression(value) + isUndefined(value) ? undefined : parseExpression(value), ), }) } @@ -168,16 +169,14 @@ export class Kysely * calls. * * ```ts - * const { count } = db.fn - * * await db.selectFrom('person') * .innerJoin('pet', 'pet.owner_id', 'person.id') - * .select([ + * .select((eb) => [ * 'person.id', - * count('pet.id').as('pet_count') + * eb.fn.count('pet.id').as('pet_count') * ]) * .groupBy('person.id') - * .having(count('pet.id'), '>', 10) + * .having((eb) => eb.fn.count('pet.id'), '>', 10) * .execute() * ``` * @@ -232,7 +231,8 @@ export class Kysely * .values({ * owner_id: jennifer.id, * name: 'Catto', - * species: 'cat' + * species: 'cat', + * is_favorite: false, * }) * .returningAll() * .executeTakeFirst() @@ -301,7 +301,7 @@ export class Kysely return new Kysely({ ...this.#props, executor: this.#props.executor.withPluginAtFront( - new WithSchemaPlugin(schema) + new WithSchemaPlugin(schema), ), }) } @@ -337,7 +337,9 @@ export class Kysely * .execute() * ``` */ - withTables>>(): Kysely { + withTables>>(): Kysely< + DrainOuterGeneric + > { return new Kysely({ ...this.#props }) } @@ -374,7 +376,7 @@ export class Kysely */ executeQuery( query: CompiledQuery | Compilable, - queryId: QueryId = createQueryId() + queryId: QueryId = createQueryId(), ): Promise> { const compiledQuery = isCompilable(query) ? query.compile() : query @@ -399,19 +401,19 @@ export class Transaction extends Kysely { transaction(): TransactionBuilder { throw new Error( - 'calling the transaction method for a Transaction is not supported' + 'calling the transaction method for a Transaction is not supported', ) } connection(): ConnectionBuilder { throw new Error( - 'calling the connection method for a Transaction is not supported' + 'calling the connection method for a Transaction is not supported', ) } async destroy(): Promise { throw new Error( - 'calling the destroy method for a Transaction is not supported' + 'calling the destroy method for a Transaction is not supported', ) } @@ -436,14 +438,14 @@ export class Transaction extends Kysely { return new Transaction({ ...this.#props, executor: this.#props.executor.withPluginAtFront( - new WithSchemaPlugin(schema) + new WithSchemaPlugin(schema), ), }) } override withTables< - T extends Record> - >(): Transaction { + T extends Record>, + >(): Transaction> { return new Transaction({ ...this.#props }) } } @@ -509,7 +511,7 @@ export class ConnectionBuilder { async execute(callback: (db: Kysely) => Promise): Promise { return this.#props.executor.provideConnection(async (connection) => { const executor = this.#props.executor.withConnectionProvider( - new SingleConnectionProvider(connection) + new SingleConnectionProvider(connection), ) const db = new Kysely({ @@ -526,7 +528,7 @@ interface ConnectionBuilderProps extends KyselyProps {} preventAwait( ConnectionBuilder, - "don't await ConnectionBuilder instances directly. To execute the query you need to call the `execute` method" + "don't await ConnectionBuilder instances directly. To execute the query you need to call the `execute` method", ) export class TransactionBuilder { @@ -551,7 +553,7 @@ export class TransactionBuilder { return this.#props.executor.provideConnection(async (connection) => { const executor = this.#props.executor.withConnectionProvider( - new SingleConnectionProvider(connection) + new SingleConnectionProvider(connection), ) const transaction = new Transaction({ @@ -579,7 +581,7 @@ interface TransactionBuilderProps extends KyselyProps { preventAwait( TransactionBuilder, - "don't await TransactionBuilder instances directly. To execute the transaction you need to call the `execute` method" + "don't await TransactionBuilder instances directly. To execute the transaction you need to call the `execute` method", ) function validateTransactionSettings(settings: TransactionSettings): void { @@ -588,7 +590,7 @@ function validateTransactionSettings(settings: TransactionSettings): void { !TRANSACTION_ISOLATION_LEVELS.includes(settings.isolationLevel) ) { throw new Error( - `invalid transaction isolation level ${settings.isolationLevel}` + `invalid transaction isolation level ${settings.isolationLevel}`, ) } } diff --git a/src/migration/file-migration-provider.ts b/src/migration/file-migration-provider.ts index 9df33e173..00e3eebac 100644 --- a/src/migration/file-migration-provider.ts +++ b/src/migration/file-migration-provider.ts @@ -38,7 +38,7 @@ export class FileMigrationProvider implements MigrationProvider { const migration = await import( /* webpackIgnore: true */ this.#props.path.join( this.#props.migrationFolder, - fileName + fileName, ) ) const migrationKey = fileName.substring(0, fileName.lastIndexOf('.')) diff --git a/src/migration/migrator.ts b/src/migration/migrator.ts index eb9f6e79a..200599245 100644 --- a/src/migration/migrator.ts +++ b/src/migration/migrator.ts @@ -3,10 +3,13 @@ import { Kysely } from '../kysely.js' import { KyselyPlugin } from '../plugin/kysely-plugin.js' import { NoopPlugin } from '../plugin/noop-plugin.js' import { WithSchemaPlugin } from '../plugin/with-schema/with-schema-plugin.js' +import { CreateSchemaBuilder } from '../schema/create-schema-builder.js' +import { CreateTableBuilder } from '../schema/create-table-builder.js' import { freeze, getLast } from '../util/object-utils.js' export const DEFAULT_MIGRATION_TABLE = 'kysely_migration' export const DEFAULT_MIGRATION_LOCK_TABLE = 'kysely_migration_lock' +export const DEFAULT_ALLOW_UNORDERED_MIGRATIONS = false export const MIGRATION_LOCK_ID = 'migration_lock' export const NO_MIGRATIONS: NoMigrations = freeze({ __noMigrations__: true }) @@ -61,7 +64,7 @@ export class Migrator { */ async getMigrations(): Promise> { const executedMigrations = (await this.#doesTableExists( - this.#migrationTable + this.#migrationTable, )) ? await this.#props.db .withPlugin(this.#schemaPlugin) @@ -94,7 +97,7 @@ export class Migrator { * This method goes through all possible migrations provided by the provider and runs the * ones whose names come alphabetically after the last migration that has been run. If the * list of executed migrations doesn't match the beginning of the list of possible migrations - * an error is thrown. + * an error is returned. * * ### Examples * @@ -131,7 +134,7 @@ export class Migrator { * ``` */ async migrateToLatest(): Promise { - return this.#migrate(({ migrations }) => migrations.length - 1) + return this.#migrate(() => ({ direction: 'Up', step: Infinity })) } /** @@ -158,23 +161,45 @@ export class Migrator { * ``` */ async migrateTo( - targetMigrationName: string | NoMigrations + targetMigrationName: string | NoMigrations, ): Promise { - return this.#migrate(({ migrations }) => { - if (targetMigrationName === NO_MIGRATIONS) { - return -1 - } + return this.#migrate( + ({ + migrations, + executedMigrations, + pendingMigrations, + }: MigrationState) => { + if (targetMigrationName === NO_MIGRATIONS) { + return { direction: 'Down', step: Infinity } + } - const index = migrations.findIndex( - (it) => it.name === targetMigrationName - ) + if ( + !migrations.find((m) => m.name === (targetMigrationName as string)) + ) { + throw new Error(`migration "${targetMigrationName}" doesn't exist`) + } - if (index === -1) { - throw new Error(`migration "${targetMigrationName}" doesn't exist`) - } + const executedIndex = executedMigrations.indexOf( + targetMigrationName as string, + ) + const pendingIndex = pendingMigrations.findIndex( + (m) => m.name === (targetMigrationName as string), + ) - return index - }) + if (executedIndex !== -1) { + return { + direction: 'Down', + step: executedMigrations.length - executedIndex - 1, + } + } else if (pendingIndex !== -1) { + return { direction: 'Up', step: pendingIndex + 1 } + } else { + throw new Error( + `migration "${targetMigrationName}" isn't executed or pending`, + ) + } + }, + ) } /** @@ -192,9 +217,7 @@ export class Migrator { * ``` */ async migrateUp(): Promise { - return this.#migrate(({ currentIndex, migrations }) => - Math.min(currentIndex + 1, migrations.length - 1) - ) + return this.#migrate(() => ({ direction: 'Up', step: 1 })) } /** @@ -212,15 +235,18 @@ export class Migrator { * ``` */ async migrateDown(): Promise { - return this.#migrate(({ currentIndex }) => Math.max(currentIndex - 1, -1)) + return this.#migrate(() => ({ direction: 'Down', step: 1 })) } async #migrate( - getTargetMigrationIndex: (state: MigrationState) => number | undefined + getMigrationDirectionAndStep: (state: MigrationState) => { + direction: MigrationDirection + step: number + }, ): Promise { try { await this.#ensureMigrationTablesExists() - return await this.#runMigrations(getTargetMigrationIndex) + return await this.#runMigrations(getMigrationDirectionAndStep) } catch (error) { if (error instanceof MigrationResultSetError) { return error.resultSet @@ -242,6 +268,12 @@ export class Migrator { return this.#props.migrationLockTableName ?? DEFAULT_MIGRATION_LOCK_TABLE } + get #allowUnorderedMigrations(): boolean { + return ( + this.#props.allowUnorderedMigrations ?? DEFAULT_ALLOW_UNORDERED_MIGRATIONS + ) + } + get #schemaPlugin(): KyselyPlugin { if (this.#migrationTableSchema) { return new WithSchemaPlugin(this.#migrationTableSchema) @@ -265,10 +297,9 @@ export class Migrator { if (!(await this.#doesSchemaExists())) { try { - await this.#props.db.schema - .createSchema(this.#migrationTableSchema) - .ifNotExists() - .execute() + await this.#createIfNotExists( + this.#props.db.schema.createSchema(this.#migrationTableSchema), + ) } catch (error) { // At least on PostgreSQL, `if not exists` doesn't guarantee the `create schema` // query doesn't throw if the schema already exits. That's why we check if @@ -284,23 +315,22 @@ export class Migrator { if (!(await this.#doesTableExists(this.#migrationTable))) { try { if (this.#migrationTableSchema) { - await this.#props.db.schema - .createSchema(this.#migrationTableSchema) - .ifNotExists() - .execute() + await this.#createIfNotExists( + this.#props.db.schema.createSchema(this.#migrationTableSchema), + ) } - await this.#props.db.schema - .withPlugin(this.#schemaPlugin) - .createTable(this.#migrationTable) - .ifNotExists() - .addColumn('name', 'varchar(255)', (col) => - col.notNull().primaryKey() - ) - // The migration run time as ISO string. This is not a real date type as we - // can't know which data type is supported by all future dialects. - .addColumn('timestamp', 'varchar(255)', (col) => col.notNull()) - .execute() + await this.#createIfNotExists( + this.#props.db.schema + .withPlugin(this.#schemaPlugin) + .createTable(this.#migrationTable) + .addColumn('name', 'varchar(255)', (col) => + col.notNull().primaryKey(), + ) + // The migration run time as ISO string. This is not a real date type as we + // can't know which data type is supported by all future dialects. + .addColumn('timestamp', 'varchar(255)', (col) => col.notNull()), + ) } catch (error) { // At least on PostgreSQL, `if not exists` doesn't guarantee the `create table` // query doesn't throw if the table already exits. That's why we check if @@ -315,15 +345,17 @@ export class Migrator { async #ensureMigrationLockTableExists(): Promise { if (!(await this.#doesTableExists(this.#migrationLockTable))) { try { - await this.#props.db.schema - .withPlugin(this.#schemaPlugin) - .createTable(this.#migrationLockTable) - .ifNotExists() - .addColumn('id', 'varchar(255)', (col) => col.notNull().primaryKey()) - .addColumn('is_locked', 'integer', (col) => - col.notNull().defaultTo(0) - ) - .execute() + await this.#createIfNotExists( + this.#props.db.schema + .withPlugin(this.#schemaPlugin) + .createTable(this.#migrationLockTable) + .addColumn('id', 'varchar(255)', (col) => + col.notNull().primaryKey(), + ) + .addColumn('is_locked', 'integer', (col) => + col.notNull().defaultTo(0), + ), + ) } catch (error) { // At least on PostgreSQL, `if not exists` doesn't guarantee the `create table` // query doesn't throw if the table already exits. That's why we check if @@ -365,7 +397,7 @@ export class Migrator { }) return tables.some( - (it) => it.name === tableName && (!schema || it.schema === schema) + (it) => it.name === tableName && (!schema || it.schema === schema), ) } @@ -381,7 +413,10 @@ export class Migrator { } async #runMigrations( - getTargetMigrationIndex: (state: MigrationState) => number | undefined + getMigrationDirectionAndStep: (state: MigrationState) => { + direction: MigrationDirection + step: number + }, ): Promise { const adapter = this.#props.db.getExecutor().adapter @@ -395,23 +430,22 @@ export class Migrator { const run = async (db: Kysely): Promise => { try { await adapter.acquireMigrationLock(db, lockOptions) - const state = await this.#getState(db) if (state.migrations.length === 0) { return { results: [] } } - const targetIndex = getTargetMigrationIndex(state) + const { direction, step } = getMigrationDirectionAndStep(state) - if (targetIndex === undefined) { + if (step <= 0) { return { results: [] } } - if (targetIndex < state.currentIndex) { - return await this.#migrateDown(db, state, targetIndex) - } else if (targetIndex > state.currentIndex) { - return await this.#migrateUp(db, state, targetIndex) + if (direction === 'Down') { + return await this.#migrateDown(db, state, step) + } else if (direction === 'Up') { + return await this.#migrateUp(db, state, step) } return { results: [] } @@ -431,13 +465,30 @@ export class Migrator { const migrations = await this.#resolveMigrations() const executedMigrations = await this.#getExecutedMigrations(db) - this.#ensureMigrationsNotCorrupted(migrations, executedMigrations) + this.#ensureNoMissingMigrations(migrations, executedMigrations) + if (!this.#allowUnorderedMigrations) { + this.#ensureMigrationsInOrder(migrations, executedMigrations) + } + + const pendingMigrations = this.#getPendingMigrations( + migrations, + executedMigrations, + ) return freeze({ migrations, - currentIndex: migrations.findIndex( - (it) => it.name === getLast(executedMigrations) - ), + executedMigrations, + lastMigration: getLast(executedMigrations), + pendingMigrations, + }) + } + + #getPendingMigrations( + migrations: ReadonlyArray, + executedMigrations: ReadonlyArray, + ): ReadonlyArray { + return migrations.filter((migration) => { + return !executedMigrations.includes(migration.name) }) } @@ -453,37 +504,41 @@ export class Migrator { } async #getExecutedMigrations( - db: Kysely + db: Kysely, ): Promise> { const executedMigrations = await db .withPlugin(this.#schemaPlugin) .selectFrom(this.#migrationTable) .select('name') - .orderBy('name') + .orderBy(['timestamp', 'name']) .execute() return executedMigrations.map((it) => it.name) } - #ensureMigrationsNotCorrupted( + #ensureNoMissingMigrations( migrations: ReadonlyArray, - executedMigrations: ReadonlyArray + executedMigrations: ReadonlyArray, ) { + // Ensure all executed migrations exist in the `migrations` list. for (const executed of executedMigrations) { if (!migrations.some((it) => it.name === executed)) { throw new Error( - `corrupted migrations: previously executed migration ${executed} is missing` + `corrupted migrations: previously executed migration ${executed} is missing`, ) } } + } - // Now we know all executed migrations exist in the `migrations` list. - // Next we need to make sure that the executed migratiosns are the first - // ones in the migration list. + #ensureMigrationsInOrder( + migrations: ReadonlyArray, + executedMigrations: ReadonlyArray, + ) { + // Ensure the executed migrations are the first ones in the migration list. for (let i = 0; i < executedMigrations.length; ++i) { if (migrations[i].name !== executedMigrations[i]) { throw new Error( - `corrupted migrations: expected previously executed migration ${executedMigrations[i]} to be at index ${i} but ${migrations[i].name} was found in its place. New migrations must always have a name that comes alphabetically after the last executed migration.` + `corrupted migrations: expected previously executed migration ${executedMigrations[i]} to be at index ${i} but ${migrations[i].name} was found in its place. New migrations must always have a name that comes alphabetically after the last executed migration.`, ) } } @@ -492,22 +547,27 @@ export class Migrator { async #migrateDown( db: Kysely, state: MigrationState, - targetIndex: number + step: number, ): Promise { - const results: MigrationResult[] = [] + const migrationsToRollback: ReadonlyArray = + state.executedMigrations + .slice() + .reverse() + .slice(0, step) + .map((name) => { + return state.migrations.find((it) => it.name === name)! + }) - for (let i = state.currentIndex; i > targetIndex; --i) { - results.push({ - migrationName: state.migrations[i].name, + const results: MigrationResult[] = migrationsToRollback.map((migration) => { + return { + migrationName: migration.name, direction: 'Down', status: 'NotExecuted', - }) - } + } + }) for (let i = 0; i < results.length; ++i) { - const migration = state.migrations.find( - (it) => it.name === results[i].migrationName - )! + const migration = migrationsToRollback[i] try { if (migration.down) { @@ -544,22 +604,21 @@ export class Migrator { async #migrateUp( db: Kysely, state: MigrationState, - targetIndex: number + step: number, ): Promise { - const results: MigrationResult[] = [] + const migrationsToRun: ReadonlyArray = + state.pendingMigrations.slice(0, step) - for (let i = state.currentIndex + 1; i <= targetIndex; ++i) { - results.push({ - migrationName: state.migrations[i].name, + const results: MigrationResult[] = migrationsToRun.map((migration) => { + return { + migrationName: migration.name, direction: 'Up', status: 'NotExecuted', - }) - } + } + }) - for (let i = 0; i < results.length; ++i) { - const migration = state.migrations.find( - (it) => it.name === results[i].migrationName - )! + for (let i = 0; i < results.length; i++) { + const migration = state.pendingMigrations[i] try { await migration.up(db) @@ -593,6 +652,16 @@ export class Migrator { return { results } } + + async #createIfNotExists( + qb: CreateTableBuilder | CreateSchemaBuilder, + ): Promise { + if (this.#props.db.getExecutor().adapter.supportsCreateIfNotExists) { + qb = qb.ifNotExists() + } + + await qb.execute() + } } export interface MigratorProps { @@ -645,6 +714,21 @@ export interface MigratorProps { * This only works on postgres. */ readonly migrationTableSchema?: string + + /** + * Enforces whether or not migrations must be run in alpha-numeric order. + * + * When false, migrations must be run in their exact alpha-numeric order. + * This is checked against the migrations already run in the database + * (`migrationTableName'). This ensures your migrations are always run in + * the same order and is the safest option. + * + * When true, migrations are still run in alpha-numeric order, but + * the order is not checked against already-run migrations in the database. + * Kysely will simply run all migrations that haven't run yet, in alpha-numeric + * order. + */ + readonly allowUnorderedMigrations?: boolean } /** @@ -682,13 +766,15 @@ export interface MigrationResultSet { readonly results?: MigrationResult[] } +type MigrationDirection = 'Up' | 'Down' + export interface MigrationResult { readonly migrationName: string /** * The direction in which this migration was executed. */ - readonly direction: 'Up' | 'Down' + readonly direction: MigrationDirection /** * The execution status. @@ -760,8 +846,14 @@ interface MigrationState { // All migrations sorted by name. readonly migrations: ReadonlyArray - // Index of the last executed migration. - readonly currentIndex: number + // Names of executed migrations sorted by execution timestamp + readonly executedMigrations: ReadonlyArray + + // Name of the last executed migration. + readonly lastMigration?: string + + // Migrations that have not yet ran + readonly pendingMigrations: ReadonlyArray } class MigrationResultSetError extends Error { diff --git a/src/operation-node/add-index-node.ts b/src/operation-node/add-index-node.ts new file mode 100644 index 000000000..986063b13 --- /dev/null +++ b/src/operation-node/add-index-node.ts @@ -0,0 +1,45 @@ +import { freeze } from '../util/object-utils.js' +import { IdentifierNode } from './identifier-node.js' +import { OperationNode } from './operation-node.js' +import { RawNode } from './raw-node.js' + +export type AddIndexNodeProps = Omit + +export interface AddIndexNode extends OperationNode { + readonly kind: 'AddIndexNode' + readonly name: IdentifierNode + readonly columns?: OperationNode[] + readonly unique?: boolean + readonly using?: RawNode + readonly ifNotExists?: boolean +} + +/** + * @internal + */ +export const AddIndexNode = freeze({ + is(node: OperationNode): node is AddIndexNode { + return node.kind === 'AddIndexNode' + }, + + create(name: string): AddIndexNode { + return freeze({ + kind: 'AddIndexNode', + name: IdentifierNode.create(name), + }) + }, + + cloneWith(node: AddIndexNode, props: AddIndexNodeProps): AddIndexNode { + return freeze({ + ...node, + ...props, + }) + }, + + cloneWithColumns(node: AddIndexNode, columns: OperationNode[]): AddIndexNode { + return freeze({ + ...node, + columns: [...(node.columns || []), ...columns], + }) + }, +}) diff --git a/src/operation-node/aggregate-function-node.ts b/src/operation-node/aggregate-function-node.ts index 5473d41ec..c8fff9e45 100644 --- a/src/operation-node/aggregate-function-node.ts +++ b/src/operation-node/aggregate-function-node.ts @@ -22,7 +22,7 @@ export const AggregateFunctionNode = freeze({ create( aggregateFunction: string, - aggregated: readonly OperationNode[] = [] + aggregated: readonly OperationNode[] = [], ): AggregateFunctionNode { return freeze({ kind: 'AggregateFunctionNode', @@ -32,7 +32,7 @@ export const AggregateFunctionNode = freeze({ }, cloneWithDistinct( - aggregateFunctionNode: AggregateFunctionNode + aggregateFunctionNode: AggregateFunctionNode, ): AggregateFunctionNode { return freeze({ ...aggregateFunctionNode, @@ -42,7 +42,7 @@ export const AggregateFunctionNode = freeze({ cloneWithFilter( aggregateFunctionNode: AggregateFunctionNode, - filter: OperationNode + filter: OperationNode, ): AggregateFunctionNode { return freeze({ ...aggregateFunctionNode, @@ -50,7 +50,7 @@ export const AggregateFunctionNode = freeze({ ? WhereNode.cloneWithOperation( aggregateFunctionNode.filter, 'And', - filter + filter, ) : WhereNode.create(filter), }) @@ -58,7 +58,7 @@ export const AggregateFunctionNode = freeze({ cloneWithOrFilter( aggregateFunctionNode: AggregateFunctionNode, - filter: OperationNode + filter: OperationNode, ): AggregateFunctionNode { return freeze({ ...aggregateFunctionNode, @@ -66,7 +66,7 @@ export const AggregateFunctionNode = freeze({ ? WhereNode.cloneWithOperation( aggregateFunctionNode.filter, 'Or', - filter + filter, ) : WhereNode.create(filter), }) @@ -74,7 +74,7 @@ export const AggregateFunctionNode = freeze({ cloneWithOver( aggregateFunctionNode: AggregateFunctionNode, - over?: OverNode + over?: OverNode, ): AggregateFunctionNode { return freeze({ ...aggregateFunctionNode, diff --git a/src/operation-node/alter-column-node.ts b/src/operation-node/alter-column-node.ts index 42e859dc3..4c2d0ff69 100644 --- a/src/operation-node/alter-column-node.ts +++ b/src/operation-node/alter-column-node.ts @@ -24,11 +24,15 @@ export const AlterColumnNode = freeze({ return node.kind === 'AlterColumnNode' }, - create(column: string, prop: T, value: Required[T]): AlterColumnNode { + create( + column: string, + prop: T, + value: Required[T], + ): AlterColumnNode { return freeze({ kind: 'AlterColumnNode', column: ColumnNode.create(column), - [prop]: value + [prop]: value, }) }, }) diff --git a/src/operation-node/alter-table-node.ts b/src/operation-node/alter-table-node.ts index fdb090eef..731ffbbc1 100644 --- a/src/operation-node/alter-table-node.ts +++ b/src/operation-node/alter-table-node.ts @@ -9,10 +9,17 @@ import { AlterColumnNode } from './alter-column-node.js' import { AddConstraintNode } from './add-constraint-node.js' import { DropConstraintNode } from './drop-constraint-node.js' import { ModifyColumnNode } from './modify-column-node.js' +import { DropIndexNode } from './drop-index-node.js' +import { AddIndexNode } from './add-index-node.js' export type AlterTableNodeTableProps = Pick< AlterTableNode, - 'renameTo' | 'setSchema' | 'addConstraint' | 'dropConstraint' + | 'renameTo' + | 'setSchema' + | 'addConstraint' + | 'dropConstraint' + | 'addIndex' + | 'dropIndex' > export type AlterTableColumnAlterationNode = @@ -30,6 +37,8 @@ export interface AlterTableNode extends OperationNode { readonly columnAlterations?: ReadonlyArray readonly addConstraint?: AddConstraintNode readonly dropConstraint?: DropConstraintNode + readonly addIndex?: AddIndexNode + readonly dropIndex?: DropIndexNode } /** @@ -49,7 +58,7 @@ export const AlterTableNode = freeze({ cloneWithTableProps( node: AlterTableNode, - props: AlterTableNodeTableProps + props: AlterTableNodeTableProps, ): AlterTableNode { return freeze({ ...node, @@ -59,7 +68,7 @@ export const AlterTableNode = freeze({ cloneWithColumnAlteration( node: AlterTableNode, - columnAlteration: AlterTableColumnAlterationNode + columnAlteration: AlterTableColumnAlterationNode, ): AlterTableNode { return freeze({ ...node, diff --git a/src/operation-node/binary-operation-node.ts b/src/operation-node/binary-operation-node.ts index 3efe15185..b06848e01 100644 --- a/src/operation-node/binary-operation-node.ts +++ b/src/operation-node/binary-operation-node.ts @@ -19,7 +19,7 @@ export const BinaryOperationNode = freeze({ create( leftOperand: OperationNode, operator: OperationNode, - rightOperand: OperationNode + rightOperand: OperationNode, ): BinaryOperationNode { return freeze({ kind: 'BinaryOperationNode', diff --git a/src/operation-node/case-node.ts b/src/operation-node/case-node.ts index a56c0400e..54d3632fa 100644 --- a/src/operation-node/case-node.ts +++ b/src/operation-node/case-node.ts @@ -40,7 +40,7 @@ export const CaseNode = freeze({ ...caseNode.when.slice(0, -1), WhenNode.cloneWithResult( caseNode.when[caseNode.when.length - 1], - then + then, ), ]) : undefined, @@ -49,7 +49,7 @@ export const CaseNode = freeze({ cloneWith( caseNode: CaseNode, - props: Partial> + props: Partial>, ): CaseNode { return freeze({ ...caseNode, diff --git a/src/operation-node/cast-node.ts b/src/operation-node/cast-node.ts new file mode 100644 index 000000000..29f46d1f9 --- /dev/null +++ b/src/operation-node/cast-node.ts @@ -0,0 +1,25 @@ +import { OperationNode } from './operation-node.js' +import { freeze } from '../util/object-utils.js' + +export interface CastNode extends OperationNode { + readonly kind: 'CastNode' + readonly expression: OperationNode + readonly dataType: OperationNode +} + +/** + * @internal + */ +export const CastNode = freeze({ + is(node: OperationNode): node is CastNode { + return node.kind === 'CastNode' + }, + + create(expression: OperationNode, dataType: OperationNode): CastNode { + return freeze({ + kind: 'CastNode', + expression, + dataType, + }) + }, +}) diff --git a/src/operation-node/check-constraint-node.ts b/src/operation-node/check-constraint-node.ts index b6a3615b9..a89e2f465 100644 --- a/src/operation-node/check-constraint-node.ts +++ b/src/operation-node/check-constraint-node.ts @@ -18,7 +18,7 @@ export const CheckConstraintNode = freeze({ create( expression: OperationNode, - constraintName?: string + constraintName?: string, ): CheckConstraintNode { return freeze({ kind: 'CheckConstraintNode', diff --git a/src/operation-node/column-definition-node.ts b/src/operation-node/column-definition-node.ts index 50335600a..30897598f 100644 --- a/src/operation-node/column-definition-node.ts +++ b/src/operation-node/column-definition-node.ts @@ -1,11 +1,9 @@ import { freeze } from '../util/object-utils.js' import { CheckConstraintNode } from './check-constraint-node.js' import { ColumnNode } from './column-node.js' -import { DataTypeNode } from './data-type-node.js' import { DefaultValueNode } from './default-value-node.js' import { GeneratedNode } from './generated-node.js' import { OperationNode } from './operation-node.js' -import { RawNode } from './raw-node.js' import { ReferencesNode } from './references-node.js' export type ColumnDefinitionNodeProps = Omit< @@ -28,6 +26,9 @@ export interface ColumnDefinitionNode extends OperationNode { readonly unsigned?: boolean readonly frontModifiers?: ReadonlyArray readonly endModifiers?: ReadonlyArray + readonly nullsNotDistinct?: boolean + readonly identity?: boolean + readonly ifNotExists?: boolean } /** @@ -48,7 +49,7 @@ export const ColumnDefinitionNode = freeze({ cloneWithFrontModifier( node: ColumnDefinitionNode, - modifier: OperationNode + modifier: OperationNode, ): ColumnDefinitionNode { return freeze({ ...node, @@ -60,7 +61,7 @@ export const ColumnDefinitionNode = freeze({ cloneWithEndModifier( node: ColumnDefinitionNode, - modifier: OperationNode + modifier: OperationNode, ): ColumnDefinitionNode { return freeze({ ...node, @@ -72,7 +73,7 @@ export const ColumnDefinitionNode = freeze({ cloneWith( node: ColumnDefinitionNode, - props: ColumnDefinitionNodeProps + props: ColumnDefinitionNodeProps, ): ColumnDefinitionNode { return freeze({ ...node, diff --git a/src/operation-node/column-update-node.ts b/src/operation-node/column-update-node.ts index e2f39b0f6..123caadfb 100644 --- a/src/operation-node/column-update-node.ts +++ b/src/operation-node/column-update-node.ts @@ -1,10 +1,9 @@ import { freeze } from '../util/object-utils.js' -import { ColumnNode } from './column-node.js' import { OperationNode } from './operation-node.js' export interface ColumnUpdateNode extends OperationNode { readonly kind: 'ColumnUpdateNode' - readonly column: ColumnNode + readonly column: OperationNode readonly value: OperationNode } @@ -16,7 +15,7 @@ export const ColumnUpdateNode = freeze({ return node.kind === 'ColumnUpdateNode' }, - create(column: ColumnNode, value: OperationNode): ColumnUpdateNode { + create(column: OperationNode, value: OperationNode): ColumnUpdateNode { return freeze({ kind: 'ColumnUpdateNode', column, diff --git a/src/operation-node/common-table-expression-name-node.ts b/src/operation-node/common-table-expression-name-node.ts index 1f23cd3b6..d0f53de22 100644 --- a/src/operation-node/common-table-expression-name-node.ts +++ b/src/operation-node/common-table-expression-name-node.ts @@ -19,7 +19,7 @@ export const CommonTableExpressionNameNode = freeze({ create( tableName: string, - columnNames?: ReadonlyArray + columnNames?: ReadonlyArray, ): CommonTableExpressionNameNode { return freeze({ kind: 'CommonTableExpressionNameNode', diff --git a/src/operation-node/common-table-expression-node.ts b/src/operation-node/common-table-expression-node.ts index 1bea44c0a..0dc982168 100644 --- a/src/operation-node/common-table-expression-node.ts +++ b/src/operation-node/common-table-expression-node.ts @@ -2,9 +2,15 @@ import { freeze } from '../util/object-utils.js' import { CommonTableExpressionNameNode } from './common-table-expression-name-node.js' import { OperationNode } from './operation-node.js' +type CommonTableExpressionNodeProps = Pick< + CommonTableExpressionNode, + 'materialized' +> + export interface CommonTableExpressionNode extends OperationNode { readonly kind: 'CommonTableExpressionNode' readonly name: CommonTableExpressionNameNode + readonly materialized?: boolean readonly expression: OperationNode } @@ -18,7 +24,7 @@ export const CommonTableExpressionNode = freeze({ create( name: CommonTableExpressionNameNode, - expression: OperationNode + expression: OperationNode, ): CommonTableExpressionNode { return freeze({ kind: 'CommonTableExpressionNode', @@ -26,4 +32,14 @@ export const CommonTableExpressionNode = freeze({ expression, }) }, + + cloneWith( + node: CommonTableExpressionNode, + props: CommonTableExpressionNodeProps, + ): CommonTableExpressionNode { + return freeze({ + ...node, + ...props, + }) + }, }) diff --git a/src/operation-node/create-index-node.ts b/src/operation-node/create-index-node.ts index c9c33adf4..7ee52cf00 100644 --- a/src/operation-node/create-index-node.ts +++ b/src/operation-node/create-index-node.ts @@ -22,6 +22,7 @@ export interface CreateIndexNode extends OperationNode { readonly using?: RawNode readonly ifNotExists?: boolean readonly where?: WhereNode + readonly nullsNotDistinct?: boolean } /** @@ -41,7 +42,7 @@ export const CreateIndexNode = freeze({ cloneWith( node: CreateIndexNode, - props: CreateIndexNodeProps + props: CreateIndexNodeProps, ): CreateIndexNode { return freeze({ ...node, @@ -51,7 +52,7 @@ export const CreateIndexNode = freeze({ cloneWithColumns( node: CreateIndexNode, - columns: OperationNode[] + columns: OperationNode[], ): CreateIndexNode { return freeze({ ...node, diff --git a/src/operation-node/create-schema-node.ts b/src/operation-node/create-schema-node.ts index 88d3cb769..27b217763 100644 --- a/src/operation-node/create-schema-node.ts +++ b/src/operation-node/create-schema-node.ts @@ -31,7 +31,7 @@ export const CreateSchemaNode = freeze({ cloneWith( createSchema: CreateSchemaNode, - params: CreateSchemaNodeParams + params: CreateSchemaNodeParams, ): CreateSchemaNode { return freeze({ ...createSchema, diff --git a/src/operation-node/create-table-node.ts b/src/operation-node/create-table-node.ts index 3638d3053..0af3cc141 100644 --- a/src/operation-node/create-table-node.ts +++ b/src/operation-node/create-table-node.ts @@ -28,6 +28,7 @@ export interface CreateTableNode extends OperationNode { readonly onCommit?: OnCommitAction readonly frontModifiers?: ReadonlyArray readonly endModifiers?: ReadonlyArray + readonly selectQuery?: OperationNode } /** @@ -48,7 +49,7 @@ export const CreateTableNode = freeze({ cloneWithColumn( createTable: CreateTableNode, - column: ColumnDefinitionNode + column: ColumnDefinitionNode, ): CreateTableNode { return freeze({ ...createTable, @@ -58,7 +59,7 @@ export const CreateTableNode = freeze({ cloneWithConstraint( createTable: CreateTableNode, - constraint: ConstraintNode + constraint: ConstraintNode, ): CreateTableNode { return freeze({ ...createTable, @@ -70,7 +71,7 @@ export const CreateTableNode = freeze({ cloneWithFrontModifier( createTable: CreateTableNode, - modifier: OperationNode + modifier: OperationNode, ): CreateTableNode { return freeze({ ...createTable, @@ -82,7 +83,7 @@ export const CreateTableNode = freeze({ cloneWithEndModifier( createTable: CreateTableNode, - modifier: OperationNode + modifier: OperationNode, ): CreateTableNode { return freeze({ ...createTable, @@ -94,7 +95,7 @@ export const CreateTableNode = freeze({ cloneWith( createTable: CreateTableNode, - params: CreateTableNodeParams + params: CreateTableNodeParams, ): CreateTableNode { return freeze({ ...createTable, diff --git a/src/operation-node/create-type-node.ts b/src/operation-node/create-type-node.ts index fe231b01d..e525e41cc 100644 --- a/src/operation-node/create-type-node.ts +++ b/src/operation-node/create-type-node.ts @@ -31,7 +31,7 @@ export const CreateTypeNode = freeze({ return freeze({ ...createType, enum: ValueListNode.create( - values.map((value) => ValueNode.createImmediate(value)) + values.map((value) => ValueNode.createImmediate(value)), ), }) }, diff --git a/src/operation-node/create-view-node.ts b/src/operation-node/create-view-node.ts index b66eb1913..fc44dbe44 100644 --- a/src/operation-node/create-view-node.ts +++ b/src/operation-node/create-view-node.ts @@ -38,7 +38,7 @@ export const CreateViewNode = freeze({ cloneWith( createView: CreateViewNode, - params: CreateViewNodeParams + params: CreateViewNodeParams, ): CreateViewNode { return freeze({ ...createView, diff --git a/src/operation-node/data-type-node.ts b/src/operation-node/data-type-node.ts index 0ff743053..2d88f43d4 100644 --- a/src/operation-node/data-type-node.ts +++ b/src/operation-node/data-type-node.ts @@ -1,46 +1,69 @@ import { freeze } from '../util/object-utils.js' import { OperationNode } from './operation-node.js' +const SIMPLE_COLUMN_DATA_TYPES = [ + 'varchar', + 'char', + 'text', + 'integer', + 'int2', + 'int4', + 'int8', + 'smallint', + 'bigint', + 'boolean', + 'real', + 'double precision', + 'float4', + 'float8', + 'decimal', + 'numeric', + 'binary', + 'bytea', + 'date', + 'datetime', + 'time', + 'timetz', + 'timestamp', + 'timestamptz', + 'serial', + 'bigserial', + 'uuid', + 'json', + 'jsonb', + 'blob', + 'varbinary', +] as const + +const COLUMN_DATA_TYPE_REGEX = [ + /^varchar\(\d+\)$/, + /^char\(\d+\)$/, + /^decimal\(\d+, \d+\)$/, + /^numeric\(\d+, \d+\)$/, + /^binary\(\d+\)$/, + /^datetime\(\d+\)$/, + /^time\(\d+\)$/, + /^timetz\(\d+\)$/, + /^timestamp\(\d+\)$/, + /^timestamptz\(\d+\)$/, + /^varbinary\(\d+\)$/, +] + +type SimpleColumnDataType = (typeof SIMPLE_COLUMN_DATA_TYPES)[number] + export type ColumnDataType = - | 'varchar' + | SimpleColumnDataType | `varchar(${number})` - | 'char' | `char(${number})` - | 'text' - | 'integer' - | 'int2' - | 'int4' - | 'int8' - | 'bigint' - | 'boolean' - | 'real' - | 'double precision' - | 'float4' - | 'float8' - | 'decimal' | `decimal(${number}, ${number})` - | 'numeric' | `numeric(${number}, ${number})` - | 'binary' | `binary(${number})` - | 'bytea' - | 'date' - | 'datetime' | `datetime(${number})` - | 'time' | `time(${number})` - | 'timetz' | `timetz(${number})` - | 'timestamp' | `timestamp(${number})` - | 'timestamptz' | `timestamptz(${number})` - | 'serial' - | 'bigserial' - | 'uuid' - | 'json' - | 'jsonb' - | 'blob' + | `varbinary(${number})` export type DataTypeParams = Omit @@ -64,3 +87,15 @@ export const DataTypeNode = freeze({ }) }, }) + +export function isColumnDataType(dataType: string): dataType is ColumnDataType { + if (SIMPLE_COLUMN_DATA_TYPES.includes(dataType as SimpleColumnDataType)) { + return true + } + + if (COLUMN_DATA_TYPE_REGEX.some((r) => r.test(dataType))) { + return true + } + + return false +} diff --git a/src/operation-node/delete-query-node.ts b/src/operation-node/delete-query-node.ts index fb44ca400..af587c7b4 100644 --- a/src/operation-node/delete-query-node.ts +++ b/src/operation-node/delete-query-node.ts @@ -10,6 +10,8 @@ import { OrderByNode } from './order-by-node.js' import { OrderByItemNode } from './order-by-item-node.js' import { ExplainNode } from './explain-node.js' import { UsingNode } from './using-node.js' +import { TopNode } from './top-node.js' +import { OutputNode } from './output-node.js' export interface DeleteQueryNode extends OperationNode { readonly kind: 'DeleteQueryNode' @@ -22,6 +24,8 @@ export interface DeleteQueryNode extends OperationNode { readonly orderBy?: OrderByNode readonly limit?: LimitNode readonly explain?: ExplainNode + readonly top?: TopNode + readonly output?: OutputNode } /** @@ -40,21 +44,28 @@ export const DeleteQueryNode = freeze({ }) }, - cloneWithOrderByItem( + cloneWithOrderByItems( deleteNode: DeleteQueryNode, - item: OrderByItemNode + items: ReadonlyArray, ): DeleteQueryNode { return freeze({ ...deleteNode, orderBy: deleteNode.orderBy - ? OrderByNode.cloneWithItem(deleteNode.orderBy, item) - : OrderByNode.create(item), + ? OrderByNode.cloneWithItems(deleteNode.orderBy, items) + : OrderByNode.create(items), + }) + }, + + cloneWithoutOrderBy(deleteNode: DeleteQueryNode): DeleteQueryNode { + return freeze({ + ...deleteNode, + orderBy: undefined, }) }, cloneWithLimit( deleteNode: DeleteQueryNode, - limit: LimitNode + limit: LimitNode, ): DeleteQueryNode { return freeze({ ...deleteNode, @@ -62,9 +73,16 @@ export const DeleteQueryNode = freeze({ }) }, + cloneWithoutLimit(deleteNode: DeleteQueryNode): DeleteQueryNode { + return freeze({ + ...deleteNode, + limit: undefined, + }) + }, + cloneWithUsing( deleteNode: DeleteQueryNode, - tables: OperationNode[] + tables: OperationNode[], ): DeleteQueryNode { return freeze({ ...deleteNode, diff --git a/src/operation-node/drop-constraint-node.ts b/src/operation-node/drop-constraint-node.ts index 36415d75e..162d90494 100644 --- a/src/operation-node/drop-constraint-node.ts +++ b/src/operation-node/drop-constraint-node.ts @@ -31,7 +31,7 @@ export const DropConstraintNode = freeze({ cloneWith( dropConstraint: DropConstraintNode, - props: DropConstraintNodeProps + props: DropConstraintNodeProps, ): DropConstraintNode { return freeze({ ...dropConstraint, diff --git a/src/operation-node/drop-index-node.ts b/src/operation-node/drop-index-node.ts index 34c49754b..0fe2ed6c4 100644 --- a/src/operation-node/drop-index-node.ts +++ b/src/operation-node/drop-index-node.ts @@ -31,7 +31,7 @@ export const DropIndexNode = freeze({ cloneWith( dropIndex: DropIndexNode, - props: DropIndexNodeProps + props: DropIndexNodeProps, ): DropIndexNode { return freeze({ ...dropIndex, diff --git a/src/operation-node/drop-schema-node.ts b/src/operation-node/drop-schema-node.ts index f34cea408..ea1930c21 100644 --- a/src/operation-node/drop-schema-node.ts +++ b/src/operation-node/drop-schema-node.ts @@ -32,7 +32,7 @@ export const DropSchemaNode = freeze({ cloneWith( dropSchema: DropSchemaNode, - params: DropSchemaNodeParams + params: DropSchemaNodeParams, ): DropSchemaNode { return freeze({ ...dropSchema, diff --git a/src/operation-node/drop-table-node.ts b/src/operation-node/drop-table-node.ts index 7116d004d..5532dd30f 100644 --- a/src/operation-node/drop-table-node.ts +++ b/src/operation-node/drop-table-node.ts @@ -31,7 +31,7 @@ export const DropTableNode = freeze({ cloneWith( dropIndex: DropTableNode, - params: DropTablexNodeParams + params: DropTablexNodeParams, ): DropTableNode { return freeze({ ...dropIndex, diff --git a/src/operation-node/fetch-node.ts b/src/operation-node/fetch-node.ts new file mode 100644 index 000000000..b682e0d77 --- /dev/null +++ b/src/operation-node/fetch-node.ts @@ -0,0 +1,27 @@ +import { OperationNode } from './operation-node.js' +import { ValueNode } from './value-node.js' + +export type FetchModifier = 'only' | 'with ties' + +export interface FetchNode extends OperationNode { + readonly kind: 'FetchNode' + readonly rowCount: ValueNode + readonly modifier: FetchModifier +} + +/** + * @internal + */ +export const FetchNode = { + is(node: OperationNode): node is FetchNode { + return node.kind === 'FetchNode' + }, + + create(rowCount: number | bigint, modifier: FetchModifier): FetchNode { + return { + kind: 'FetchNode', + rowCount: ValueNode.create(rowCount), + modifier, + } + }, +} diff --git a/src/operation-node/foreign-key-constraint-node.ts b/src/operation-node/foreign-key-constraint-node.ts index 89a62b129..b15172e87 100644 --- a/src/operation-node/foreign-key-constraint-node.ts +++ b/src/operation-node/foreign-key-constraint-node.ts @@ -31,7 +31,7 @@ export const ForeignKeyConstraintNode = freeze({ sourceColumns: ReadonlyArray, targetTable: TableNode, targetColumns: ReadonlyArray, - constraintName?: string + constraintName?: string, ): ForeignKeyConstraintNode { return freeze({ kind: 'ForeignKeyConstraintNode', @@ -43,7 +43,7 @@ export const ForeignKeyConstraintNode = freeze({ cloneWith( node: ForeignKeyConstraintNode, - props: ForeignKeyConstraintNodeProps + props: ForeignKeyConstraintNodeProps, ) { return freeze({ ...node, diff --git a/src/operation-node/from-node.ts b/src/operation-node/from-node.ts index 8e5a08cd1..83f5aea69 100644 --- a/src/operation-node/from-node.ts +++ b/src/operation-node/from-node.ts @@ -23,7 +23,7 @@ export const FromNode = freeze({ cloneWithFroms( from: FromNode, - froms: ReadonlyArray + froms: ReadonlyArray, ): FromNode { return freeze({ ...from, diff --git a/src/operation-node/group-by-node.ts b/src/operation-node/group-by-node.ts index d9e3c6aba..f1a68871d 100644 --- a/src/operation-node/group-by-node.ts +++ b/src/operation-node/group-by-node.ts @@ -24,7 +24,7 @@ export const GroupByNode = freeze({ cloneWithItems( groupBy: GroupByNode, - items: ReadonlyArray + items: ReadonlyArray, ): GroupByNode { return freeze({ ...groupBy, diff --git a/src/operation-node/having-node.ts b/src/operation-node/having-node.ts index c329f413a..add723df0 100644 --- a/src/operation-node/having-node.ts +++ b/src/operation-node/having-node.ts @@ -26,7 +26,7 @@ export const HavingNode = freeze({ cloneWithOperation( havingNode: HavingNode, operator: 'And' | 'Or', - operation: OperationNode + operation: OperationNode, ): HavingNode { return freeze({ ...havingNode, diff --git a/src/operation-node/insert-query-node.ts b/src/operation-node/insert-query-node.ts index eb6553b96..e95240a22 100644 --- a/src/operation-node/insert-query-node.ts +++ b/src/operation-node/insert-query-node.ts @@ -4,15 +4,17 @@ import { ExplainNode } from './explain-node.js' import { OnConflictNode } from './on-conflict-node.js' import { OnDuplicateKeyNode } from './on-duplicate-key-node.js' import { OperationNode } from './operation-node.js' +import { OutputNode } from './output-node.js' import { ReturningNode } from './returning-node.js' import { TableNode } from './table-node.js' +import { TopNode } from './top-node.js' import { WithNode } from './with-node.js' export type InsertQueryNodeProps = Omit export interface InsertQueryNode extends OperationNode { readonly kind: 'InsertQueryNode' - readonly into: TableNode + readonly into?: TableNode readonly columns?: ReadonlyArray readonly values?: OperationNode readonly returning?: ReturningNode @@ -22,6 +24,9 @@ export interface InsertQueryNode extends OperationNode { readonly ignore?: boolean readonly replace?: boolean readonly explain?: ExplainNode + readonly defaultValues?: boolean + readonly top?: TopNode + readonly output?: OutputNode } /** @@ -35,7 +40,7 @@ export const InsertQueryNode = freeze({ create( into: TableNode, withNode?: WithNode, - replace?: boolean + replace?: boolean, ): InsertQueryNode { return freeze({ kind: 'InsertQueryNode', @@ -45,9 +50,15 @@ export const InsertQueryNode = freeze({ }) }, + createWithoutInto(): InsertQueryNode { + return freeze({ + kind: 'InsertQueryNode', + }) + }, + cloneWith( insertQuery: InsertQueryNode, - props: InsertQueryNodeProps + props: InsertQueryNodeProps, ): InsertQueryNode { return freeze({ ...insertQuery, diff --git a/src/operation-node/join-node.ts b/src/operation-node/join-node.ts index ae83b223a..cbbe93a67 100644 --- a/src/operation-node/join-node.ts +++ b/src/operation-node/join-node.ts @@ -1,8 +1,6 @@ import { freeze } from '../util/object-utils.js' -import { AliasNode } from './alias-node.js' import { OnNode } from './on-node.js' import { OperationNode } from './operation-node.js' -import { TableNode } from './table-node.js' export type JoinType = | 'InnerJoin' @@ -11,6 +9,7 @@ export type JoinType = | 'FullJoin' | 'LateralInnerJoin' | 'LateralLeftJoin' + | 'Using' export interface JoinNode extends OperationNode { readonly kind: 'JoinNode' @@ -39,7 +38,7 @@ export const JoinNode = freeze({ createWithOn( joinType: JoinType, table: OperationNode, - on: OperationNode + on: OperationNode, ): JoinNode { return freeze({ kind: 'JoinNode', @@ -57,13 +56,4 @@ export const JoinNode = freeze({ : OnNode.create(operation), }) }, - - cloneWithOrOn(joinNode: JoinNode, operation: OperationNode): JoinNode { - return freeze({ - ...joinNode, - on: joinNode.on - ? OnNode.cloneWithOperation(joinNode.on, 'Or', operation) - : OnNode.create(operation), - }) - }, }) diff --git a/src/operation-node/json-operator-chain-node.ts b/src/operation-node/json-operator-chain-node.ts new file mode 100644 index 000000000..5d0ac6d72 --- /dev/null +++ b/src/operation-node/json-operator-chain-node.ts @@ -0,0 +1,37 @@ +import { freeze } from '../util/object-utils.js' +import { OperationNode } from './operation-node.js' +import { OperatorNode } from './operator-node.js' +import { ValueNode } from './value-node.js' + +export interface JSONOperatorChainNode extends OperationNode { + readonly kind: 'JSONOperatorChainNode' + readonly operator: OperatorNode + readonly values: readonly ValueNode[] +} + +/** + * @internal + */ +export const JSONOperatorChainNode = freeze({ + is(node: OperationNode): node is JSONOperatorChainNode { + return node.kind === 'JSONOperatorChainNode' + }, + + create(operator: OperatorNode): JSONOperatorChainNode { + return freeze({ + kind: 'JSONOperatorChainNode', + operator, + values: freeze([]), + }) + }, + + cloneWithValue( + node: JSONOperatorChainNode, + value: ValueNode, + ): JSONOperatorChainNode { + return freeze({ + ...node, + values: freeze([...node.values, value]), + }) + }, +}) diff --git a/src/operation-node/json-path-leg-node.ts b/src/operation-node/json-path-leg-node.ts new file mode 100644 index 000000000..08a7c83c9 --- /dev/null +++ b/src/operation-node/json-path-leg-node.ts @@ -0,0 +1,27 @@ +import { freeze } from '../util/object-utils.js' +import { OperationNode } from './operation-node.js' + +export type JSONPathLegType = 'Member' | 'ArrayLocation' + +export interface JSONPathLegNode extends OperationNode { + readonly kind: 'JSONPathLegNode' + readonly type: JSONPathLegType + readonly value: string | number +} + +/** + * @internal + */ +export const JSONPathLegNode = freeze({ + is(node: OperationNode): node is JSONPathLegNode { + return node.kind === 'JSONPathLegNode' + }, + + create(type: JSONPathLegType, value: string | number): JSONPathLegNode { + return freeze({ + kind: 'JSONPathLegNode', + type, + value, + }) + }, +}) diff --git a/src/operation-node/json-path-node.ts b/src/operation-node/json-path-node.ts new file mode 100644 index 000000000..4598a80a8 --- /dev/null +++ b/src/operation-node/json-path-node.ts @@ -0,0 +1,37 @@ +import { freeze } from '../util/object-utils.js' +import { JSONPathLegNode } from './json-path-leg-node.js' +import { OperationNode } from './operation-node.js' +import { OperatorNode } from './operator-node.js' + +export interface JSONPathNode extends OperationNode { + readonly kind: 'JSONPathNode' + readonly inOperator?: OperatorNode + readonly pathLegs: ReadonlyArray +} + +/** + * @internal + */ +export const JSONPathNode = freeze({ + is(node: OperationNode): node is JSONPathNode { + return node.kind === 'JSONPathNode' + }, + + create(inOperator?: OperatorNode): JSONPathNode { + return freeze({ + kind: 'JSONPathNode', + inOperator, + pathLegs: freeze([]), + }) + }, + + cloneWithLeg( + jsonPathNode: JSONPathNode, + pathLeg: JSONPathLegNode, + ): JSONPathNode { + return freeze({ + ...jsonPathNode, + pathLegs: freeze([...jsonPathNode.pathLegs, pathLeg]), + }) + }, +}) diff --git a/src/operation-node/json-reference-node.ts b/src/operation-node/json-reference-node.ts new file mode 100644 index 000000000..0a35e838d --- /dev/null +++ b/src/operation-node/json-reference-node.ts @@ -0,0 +1,41 @@ +import { freeze } from '../util/object-utils.js' +import { JSONOperatorChainNode } from './json-operator-chain-node.js' +import { JSONPathNode } from './json-path-node.js' +import { OperationNode } from './operation-node.js' +import { ReferenceNode } from './reference-node.js' + +export interface JSONReferenceNode extends OperationNode { + readonly kind: 'JSONReferenceNode' + readonly reference: ReferenceNode + readonly traversal: JSONPathNode | JSONOperatorChainNode +} + +/** + * @internal + */ +export const JSONReferenceNode = freeze({ + is(node: OperationNode): node is JSONReferenceNode { + return node.kind === 'JSONReferenceNode' + }, + + create( + reference: ReferenceNode, + traversal: JSONPathNode | JSONOperatorChainNode, + ): JSONReferenceNode { + return freeze({ + kind: 'JSONReferenceNode', + reference, + traversal, + }) + }, + + cloneWithTraversal( + node: JSONReferenceNode, + traversal: JSONPathNode | JSONOperatorChainNode, + ): JSONReferenceNode { + return freeze({ + ...node, + traversal, + }) + }, +}) diff --git a/src/operation-node/limit-node.ts b/src/operation-node/limit-node.ts index b651c7a89..a74306be1 100644 --- a/src/operation-node/limit-node.ts +++ b/src/operation-node/limit-node.ts @@ -1,10 +1,9 @@ import { freeze } from '../util/object-utils.js' import { OperationNode } from './operation-node.js' -import { ValueNode } from './value-node.js' export interface LimitNode extends OperationNode { readonly kind: 'LimitNode' - readonly limit: ValueNode + readonly limit: OperationNode } /** @@ -15,10 +14,10 @@ export const LimitNode = freeze({ return node.kind === 'LimitNode' }, - create(limit: number): LimitNode { + create(limit: OperationNode): LimitNode { return freeze({ kind: 'LimitNode', - limit: ValueNode.create(limit), + limit, }) }, }) diff --git a/src/operation-node/matched-node.ts b/src/operation-node/matched-node.ts new file mode 100644 index 000000000..f6c4ddd4f --- /dev/null +++ b/src/operation-node/matched-node.ts @@ -0,0 +1,25 @@ +import { freeze } from '../util/object-utils.js' +import { OperationNode } from './operation-node.js' + +export interface MatchedNode extends OperationNode { + readonly kind: 'MatchedNode' + readonly not: boolean + readonly bySource: boolean +} + +/** + * @internal + */ +export const MatchedNode = freeze({ + is(node: OperationNode): node is MatchedNode { + return node.kind === 'MatchedNode' + }, + + create(not: boolean, bySource: boolean = false): MatchedNode { + return freeze({ + kind: 'MatchedNode', + not, + bySource, + }) + }, +}) diff --git a/src/operation-node/merge-query-node.ts b/src/operation-node/merge-query-node.ts new file mode 100644 index 000000000..7b202d4c0 --- /dev/null +++ b/src/operation-node/merge-query-node.ts @@ -0,0 +1,70 @@ +import { freeze } from '../util/object-utils.js' +import { AliasNode } from './alias-node.js' +import { JoinNode } from './join-node.js' +import { OperationNode } from './operation-node.js' +import { OutputNode } from './output-node.js' +import { TableNode } from './table-node.js' +import { TopNode } from './top-node.js' +import { WhenNode } from './when-node.js' +import { WithNode } from './with-node.js' + +export interface MergeQueryNode extends OperationNode { + readonly kind: 'MergeQueryNode' + readonly into: TableNode | AliasNode + readonly using?: JoinNode + readonly whens?: ReadonlyArray + readonly with?: WithNode + readonly top?: TopNode + readonly output?: OutputNode +} + +/** + * @internal + */ +export const MergeQueryNode = freeze({ + is(node: OperationNode): node is MergeQueryNode { + return node.kind === 'MergeQueryNode' + }, + + create(into: TableNode | AliasNode, withNode?: WithNode): MergeQueryNode { + return freeze({ + kind: 'MergeQueryNode', + into, + ...(withNode && { with: withNode }), + }) + }, + + cloneWithUsing(mergeNode: MergeQueryNode, using: JoinNode): MergeQueryNode { + return freeze({ + ...mergeNode, + using, + }) + }, + + cloneWithWhen(mergeNode: MergeQueryNode, when: WhenNode): MergeQueryNode { + return freeze({ + ...mergeNode, + whens: mergeNode.whens + ? freeze([...mergeNode.whens, when]) + : freeze([when]), + }) + }, + + cloneWithThen( + mergeNode: MergeQueryNode, + then: OperationNode, + ): MergeQueryNode { + return freeze({ + ...mergeNode, + whens: mergeNode.whens + ? freeze([ + ...mergeNode.whens.slice(0, -1), + WhenNode.cloneWithResult( + mergeNode.whens[mergeNode.whens.length - 1], + then, + ), + ]) + : undefined, + }) + }, +}) diff --git a/src/operation-node/offset-node.ts b/src/operation-node/offset-node.ts index 04e1bd80e..e4d8b6452 100644 --- a/src/operation-node/offset-node.ts +++ b/src/operation-node/offset-node.ts @@ -1,10 +1,9 @@ import { freeze } from '../util/object-utils.js' import { OperationNode } from './operation-node.js' -import { ValueNode } from './value-node.js' export interface OffsetNode extends OperationNode { readonly kind: 'OffsetNode' - readonly offset: ValueNode + readonly offset: OperationNode } /** @@ -15,10 +14,10 @@ export const OffsetNode = freeze({ return node.kind === 'OffsetNode' }, - create(offset: number): OffsetNode { + create(offset: OperationNode): OffsetNode { return freeze({ kind: 'OffsetNode', - offset: ValueNode.create(offset), + offset, }) }, }) diff --git a/src/operation-node/on-conflict-node.ts b/src/operation-node/on-conflict-node.ts index bf9212c92..59208d1b7 100644 --- a/src/operation-node/on-conflict-node.ts +++ b/src/operation-node/on-conflict-node.ts @@ -44,7 +44,7 @@ export const OnConflictNode = freeze({ cloneWithIndexWhere( node: OnConflictNode, - operation: OperationNode + operation: OperationNode, ): OnConflictNode { return freeze({ ...node, @@ -56,7 +56,7 @@ export const OnConflictNode = freeze({ cloneWithIndexOrWhere( node: OnConflictNode, - operation: OperationNode + operation: OperationNode, ): OnConflictNode { return freeze({ ...node, @@ -68,7 +68,7 @@ export const OnConflictNode = freeze({ cloneWithUpdateWhere( node: OnConflictNode, - operation: OperationNode + operation: OperationNode, ): OnConflictNode { return freeze({ ...node, @@ -80,7 +80,7 @@ export const OnConflictNode = freeze({ cloneWithUpdateOrWhere( node: OnConflictNode, - operation: OperationNode + operation: OperationNode, ): OnConflictNode { return freeze({ ...node, diff --git a/src/operation-node/on-node.ts b/src/operation-node/on-node.ts index a4cbb01f9..0574ef085 100644 --- a/src/operation-node/on-node.ts +++ b/src/operation-node/on-node.ts @@ -26,7 +26,7 @@ export const OnNode = freeze({ cloneWithOperation( onNode: OnNode, operator: 'And' | 'Or', - operation: OperationNode + operation: OperationNode, ): OnNode { return freeze({ ...onNode, diff --git a/src/operation-node/operation-node-source.ts b/src/operation-node/operation-node-source.ts index abee522dc..0747c1a97 100644 --- a/src/operation-node/operation-node-source.ts +++ b/src/operation-node/operation-node-source.ts @@ -6,7 +6,7 @@ export interface OperationNodeSource { } export function isOperationNodeSource( - obj: unknown + obj: unknown, ): obj is OperationNodeSource { return isObject(obj) && isFunction(obj.toOperationNode) } diff --git a/src/operation-node/operation-node-transformer.ts b/src/operation-node/operation-node-transformer.ts index 28520b177..bd4b74ef1 100644 --- a/src/operation-node/operation-node-transformer.ts +++ b/src/operation-node/operation-node-transformer.ts @@ -82,6 +82,18 @@ import { UsingNode } from './using-node.js' import { FunctionNode } from './function-node.js' import { CaseNode } from './case-node.js' import { WhenNode } from './when-node.js' +import { JSONReferenceNode } from './json-reference-node.js' +import { JSONPathNode } from './json-path-node.js' +import { JSONPathLegNode } from './json-path-leg-node.js' +import { JSONOperatorChainNode } from './json-operator-chain-node.js' +import { TupleNode } from './tuple-node.js' +import { MergeQueryNode } from './merge-query-node.js' +import { MatchedNode } from './matched-node.js' +import { AddIndexNode } from './add-index-node.js' +import { CastNode } from './cast-node.js' +import { FetchNode } from './fetch-node.js' +import { TopNode } from './top-node.js' +import { OutputNode } from './output-node.js' /** * Transforms an operation node tree into another one. @@ -198,6 +210,18 @@ export class OperationNodeTransformer { FunctionNode: this.transformFunction.bind(this), CaseNode: this.transformCase.bind(this), WhenNode: this.transformWhen.bind(this), + JSONReferenceNode: this.transformJSONReference.bind(this), + JSONPathNode: this.transformJSONPath.bind(this), + JSONPathLegNode: this.transformJSONPathLeg.bind(this), + JSONOperatorChainNode: this.transformJSONOperatorChain.bind(this), + TupleNode: this.transformTuple.bind(this), + MergeQueryNode: this.transformMergeQuery.bind(this), + MatchedNode: this.transformMatched.bind(this), + AddIndexNode: this.transformAddIndex.bind(this), + CastNode: this.transformCast.bind(this), + FetchNode: this.transformFetch.bind(this), + TopNode: this.transformTop.bind(this), + OutputNode: this.transformOutput.bind(this), }) transformNode(node: T): T { @@ -217,7 +241,7 @@ export class OperationNodeTransformer { } protected transformNodeList< - T extends ReadonlyArray | undefined + T extends ReadonlyArray | undefined, >(list: T): T { if (!list) { return list @@ -244,6 +268,8 @@ export class OperationNodeTransformer { having: this.transformNode(node.having), explain: this.transformNode(node.explain), setOperations: this.transformNodeList(node.setOperations), + fetch: this.transformNode(node.fetch), + top: this.transformNode(node.top), }) } @@ -286,8 +312,8 @@ export class OperationNodeTransformer { protected transformReference(node: ReferenceNode): ReferenceNode { return requireAllProps({ kind: 'ReferenceNode', - table: this.transformNode(node.table), column: this.transformNode(node.column), + table: this.transformNode(node.table), }) } @@ -358,6 +384,9 @@ export class OperationNodeTransformer { ignore: node.ignore, replace: node.replace, explain: this.transformNode(node.explain), + defaultValues: node.defaultValues, + top: this.transformNode(node.top), + output: this.transformNode(node.output), }) } @@ -380,6 +409,8 @@ export class OperationNodeTransformer { orderBy: this.transformNode(node.orderBy), limit: this.transformNode(node.limit), explain: this.transformNode(node.explain), + top: this.transformNode(node.top), + output: this.transformNode(node.output), }) } @@ -401,11 +432,12 @@ export class OperationNodeTransformer { onCommit: node.onCommit, frontModifiers: this.transformNodeList(node.frontModifiers), endModifiers: this.transformNodeList(node.endModifiers), + selectQuery: this.transformNode(node.selectQuery), }) } protected transformColumnDefinition( - node: ColumnDefinitionNode + node: ColumnDefinitionNode, ): ColumnDefinitionNode { return requireAllProps({ kind: 'ColumnDefinitionNode', @@ -422,6 +454,9 @@ export class OperationNodeTransformer { generated: this.transformNode(node.generated), frontModifiers: this.transformNodeList(node.frontModifiers), endModifiers: this.transformNodeList(node.endModifiers), + nullsNotDistinct: node.nullsNotDistinct, + identity: node.identity, + ifNotExists: node.ifNotExists, }) } @@ -481,6 +516,9 @@ export class OperationNodeTransformer { returning: this.transformNode(node.returning), with: this.transformNode(node.with), explain: this.transformNode(node.explain), + limit: this.transformNode(node.limit), + top: this.transformNode(node.top), + output: this.transformNode(node.output), }) } @@ -520,7 +558,7 @@ export class OperationNodeTransformer { } protected transformOnDuplicateKey( - node: OnDuplicateKeyNode + node: OnDuplicateKeyNode, ): OnDuplicateKeyNode { return requireAllProps({ kind: 'OnDuplicateKeyNode', @@ -538,6 +576,7 @@ export class OperationNodeTransformer { using: this.transformNode(node.using), ifNotExists: node.ifNotExists, where: this.transformNode(node.where), + nullsNotDistinct: node.nullsNotDistinct, }) } @@ -559,7 +598,7 @@ export class OperationNodeTransformer { } protected transformPrimaryKeyConstraint( - node: PrimaryKeyConstraintNode + node: PrimaryKeyConstraintNode, ): PrimaryKeyConstraintNode { return requireAllProps({ kind: 'PrimaryKeyConstraintNode', @@ -569,17 +608,18 @@ export class OperationNodeTransformer { } protected transformUniqueConstraint( - node: UniqueConstraintNode + node: UniqueConstraintNode, ): UniqueConstraintNode { return requireAllProps({ kind: 'UniqueConstraintNode', columns: this.transformNodeList(node.columns), name: this.transformNode(node.name), + nullsNotDistinct: node.nullsNotDistinct, }) } protected transformForeignKeyConstraint( - node: ForeignKeyConstraintNode + node: ForeignKeyConstraintNode, ): ForeignKeyConstraintNode { return requireAllProps({ kind: 'ForeignKeyConstraintNode', @@ -611,7 +651,7 @@ export class OperationNodeTransformer { } protected transformCheckConstraint( - node: CheckConstraintNode + node: CheckConstraintNode, ): CheckConstraintNode { return requireAllProps({ kind: 'CheckConstraintNode', @@ -629,17 +669,18 @@ export class OperationNodeTransformer { } protected transformCommonTableExpression( - node: CommonTableExpressionNode + node: CommonTableExpressionNode, ): CommonTableExpressionNode { return requireAllProps({ kind: 'CommonTableExpressionNode', name: this.transformNode(node.name), + materialized: node.materialized, expression: this.transformNode(node.expression), }) } protected transformCommonTableExpressionName( - node: CommonTableExpressionNameNode + node: CommonTableExpressionNameNode, ): CommonTableExpressionNameNode { return requireAllProps({ kind: 'CommonTableExpressionNameNode', @@ -681,6 +722,8 @@ export class OperationNodeTransformer { columnAlterations: this.transformNodeList(node.columnAlterations), addConstraint: this.transformNode(node.addConstraint), dropConstraint: this.transformNode(node.dropConstraint), + addIndex: this.transformNode(node.addIndex), + dropIndex: this.transformNode(node.dropIndex), }) } @@ -727,7 +770,7 @@ export class OperationNodeTransformer { } protected transformDropConstraint( - node: DropConstraintNode + node: DropConstraintNode, ): DropConstraintNode { return requireAllProps({ kind: 'DropConstraintNode', @@ -786,12 +829,13 @@ export class OperationNodeTransformer { } protected transformSelectModifier( - node: SelectModifierNode + node: SelectModifierNode, ): SelectModifierNode { return requireAllProps({ kind: 'SelectModifierNode', modifier: node.modifier, rawModifier: this.transformNode(node.rawModifier), + of: this.transformNodeList(node.of), }) } @@ -820,7 +864,7 @@ export class OperationNodeTransformer { } protected transformSchemableIdentifier( - node: SchemableIdentifierNode + node: SchemableIdentifierNode, ): SchemableIdentifierNode { return requireAllProps({ kind: 'SchemableIdentifierNode', @@ -830,7 +874,7 @@ export class OperationNodeTransformer { } protected transformAggregateFunction( - node: AggregateFunctionNode + node: AggregateFunctionNode, ): AggregateFunctionNode { return requireAllProps({ kind: 'AggregateFunctionNode', @@ -858,7 +902,7 @@ export class OperationNodeTransformer { } protected transformPartitionByItem( - node: PartitionByItemNode + node: PartitionByItemNode, ): PartitionByItemNode { return requireAllProps({ kind: 'PartitionByItemNode', @@ -867,7 +911,7 @@ export class OperationNodeTransformer { } protected transformBinaryOperation( - node: BinaryOperationNode + node: BinaryOperationNode, ): BinaryOperationNode { return requireAllProps({ kind: 'BinaryOperationNode', @@ -878,7 +922,7 @@ export class OperationNodeTransformer { } protected transformUnaryOperation( - node: UnaryOperationNode + node: UnaryOperationNode, ): UnaryOperationNode { return requireAllProps({ kind: 'UnaryOperationNode', @@ -920,6 +964,109 @@ export class OperationNodeTransformer { }) } + protected transformJSONReference(node: JSONReferenceNode): JSONReferenceNode { + return requireAllProps({ + kind: 'JSONReferenceNode', + reference: this.transformNode(node.reference), + traversal: this.transformNode(node.traversal), + }) + } + + protected transformJSONPath(node: JSONPathNode): JSONPathNode { + return requireAllProps({ + kind: 'JSONPathNode', + inOperator: this.transformNode(node.inOperator), + pathLegs: this.transformNodeList(node.pathLegs), + }) + } + + protected transformJSONPathLeg(node: JSONPathLegNode): JSONPathLegNode { + return requireAllProps({ + kind: 'JSONPathLegNode', + type: node.type, + value: node.value, + }) + } + + protected transformJSONOperatorChain( + node: JSONOperatorChainNode, + ): JSONOperatorChainNode { + return requireAllProps({ + kind: 'JSONOperatorChainNode', + operator: this.transformNode(node.operator), + values: this.transformNodeList(node.values), + }) + } + + protected transformTuple(node: TupleNode): TupleNode { + return requireAllProps({ + kind: 'TupleNode', + values: this.transformNodeList(node.values), + }) + } + + protected transformMergeQuery(node: MergeQueryNode): MergeQueryNode { + return requireAllProps({ + kind: 'MergeQueryNode', + into: this.transformNode(node.into), + using: this.transformNode(node.using), + whens: this.transformNodeList(node.whens), + with: this.transformNode(node.with), + top: this.transformNode(node.top), + output: this.transformNode(node.output), + }) + } + + protected transformMatched(node: MatchedNode): MatchedNode { + return requireAllProps({ + kind: 'MatchedNode', + not: node.not, + bySource: node.bySource, + }) + } + + protected transformAddIndex(node: AddIndexNode): AddIndexNode { + return requireAllProps({ + kind: 'AddIndexNode', + name: this.transformNode(node.name), + columns: this.transformNodeList(node.columns), + unique: node.unique, + using: this.transformNode(node.using), + ifNotExists: node.ifNotExists, + }) + } + + protected transformCast(node: CastNode): CastNode { + return requireAllProps({ + kind: 'CastNode', + expression: this.transformNode(node.expression), + dataType: this.transformNode(node.dataType), + }) + } + + protected transformFetch(node: FetchNode): FetchNode { + return requireAllProps({ + kind: 'FetchNode', + rowCount: this.transformNode(node.rowCount), + modifier: node.modifier, + }) + } + + protected transformTop(node: TopNode): TopNode { + return requireAllProps({ + kind: 'TopNode', + expression: node.expression, + modifiers: node.modifiers, + }) + } + + protected transformOutput(node: OutputNode): OutputNode { + return requireAllProps({ + kind: 'OutputNode', + selections: this.transformNodeList(node.selections), + }) + } + protected transformDataType(node: DataTypeNode): DataTypeNode { // An Object.freezed leaf node. No need to clone. return node @@ -941,7 +1088,7 @@ export class OperationNodeTransformer { } protected transformPrimitiveValueList( - node: PrimitiveValueListNode + node: PrimitiveValueListNode, ): PrimitiveValueListNode { // An Object.freezed leaf node. No need to clone. return node @@ -953,7 +1100,7 @@ export class OperationNodeTransformer { } protected transformDefaultInsertValue( - node: DefaultInsertValueNode + node: DefaultInsertValueNode, ): DefaultInsertValueNode { // An Object.freezed leaf node. No need to clone. return node diff --git a/src/operation-node/operation-node-visitor.ts b/src/operation-node/operation-node-visitor.ts index 5a9871b4f..f88f12539 100644 --- a/src/operation-node/operation-node-visitor.ts +++ b/src/operation-node/operation-node-visitor.ts @@ -84,6 +84,18 @@ import { UsingNode } from './using-node.js' import { FunctionNode } from './function-node.js' import { WhenNode } from './when-node.js' import { CaseNode } from './case-node.js' +import { JSONReferenceNode } from './json-reference-node.js' +import { JSONPathNode } from './json-path-node.js' +import { JSONPathLegNode } from './json-path-leg-node.js' +import { JSONOperatorChainNode } from './json-operator-chain-node.js' +import { TupleNode } from './tuple-node.js' +import { MergeQueryNode } from './merge-query-node.js' +import { MatchedNode } from './matched-node.js' +import { AddIndexNode } from './add-index-node.js' +import { CastNode } from './cast-node.js' +import { FetchNode } from './fetch-node.js' +import { TopNode } from './top-node.js' +import { OutputNode } from './output-node.js' export abstract class OperationNodeVisitor { protected readonly nodeStack: OperationNode[] = [] @@ -175,6 +187,18 @@ export abstract class OperationNodeVisitor { FunctionNode: this.visitFunction.bind(this), CaseNode: this.visitCase.bind(this), WhenNode: this.visitWhen.bind(this), + JSONReferenceNode: this.visitJSONReference.bind(this), + JSONPathNode: this.visitJSONPath.bind(this), + JSONPathLegNode: this.visitJSONPathLeg.bind(this), + JSONOperatorChainNode: this.visitJSONOperatorChain.bind(this), + TupleNode: this.visitTuple.bind(this), + MergeQueryNode: this.visitMergeQuery.bind(this), + MatchedNode: this.visitMatched.bind(this), + AddIndexNode: this.visitAddIndex.bind(this), + CastNode: this.visitCast.bind(this), + FetchNode: this.visitFetch.bind(this), + TopNode: this.visitTop.bind(this), + OutputNode: this.visitOutput.bind(this), }) protected readonly visitNode = (node: OperationNode): void => { @@ -218,17 +242,17 @@ export abstract class OperationNodeVisitor { protected abstract visitDropIndex(node: DropIndexNode): void protected abstract visitList(node: ListNode): void protected abstract visitPrimaryKeyConstraint( - node: PrimaryKeyConstraintNode + node: PrimaryKeyConstraintNode, ): void protected abstract visitUniqueConstraint(node: UniqueConstraintNode): void protected abstract visitReferences(node: ReferencesNode): void protected abstract visitCheckConstraint(node: CheckConstraintNode): void protected abstract visitWith(node: WithNode): void protected abstract visitCommonTableExpression( - node: CommonTableExpressionNode + node: CommonTableExpressionNode, ): void protected abstract visitCommonTableExpressionName( - node: CommonTableExpressionNameNode + node: CommonTableExpressionNameNode, ): void protected abstract visitHaving(node: HavingNode): void protected abstract visitCreateSchema(node: CreateSchemaNode): void @@ -241,13 +265,13 @@ export abstract class OperationNodeVisitor { protected abstract visitAddConstraint(node: AddConstraintNode): void protected abstract visitDropConstraint(node: DropConstraintNode): void protected abstract visitForeignKeyConstraint( - node: ForeignKeyConstraintNode + node: ForeignKeyConstraintNode, ): void protected abstract visitDataType(node: DataTypeNode): void protected abstract visitSelectAll(node: SelectAllNode): void protected abstract visitIdentifier(node: IdentifierNode): void protected abstract visitSchemableIdentifier( - node: SchemableIdentifierNode + node: SchemableIdentifierNode, ): void protected abstract visitValue(node: ValueNode): void protected abstract visitPrimitiveValueList(node: PrimitiveValueListNode): void @@ -274,4 +298,16 @@ export abstract class OperationNodeVisitor { protected abstract visitFunction(node: FunctionNode): void protected abstract visitCase(node: CaseNode): void protected abstract visitWhen(node: WhenNode): void + protected abstract visitJSONReference(node: JSONReferenceNode): void + protected abstract visitJSONPath(node: JSONPathNode): void + protected abstract visitJSONPathLeg(node: JSONPathLegNode): void + protected abstract visitJSONOperatorChain(node: JSONOperatorChainNode): void + protected abstract visitTuple(node: TupleNode): void + protected abstract visitMergeQuery(node: MergeQueryNode): void + protected abstract visitMatched(node: MatchedNode): void + protected abstract visitAddIndex(node: AddIndexNode): void + protected abstract visitCast(node: CastNode): void + protected abstract visitFetch(node: FetchNode): void + protected abstract visitTop(node: TopNode): void + protected abstract visitOutput(node: OutputNode): void } diff --git a/src/operation-node/operation-node.ts b/src/operation-node/operation-node.ts index 04bb9122e..6476a24eb 100644 --- a/src/operation-node/operation-node.ts +++ b/src/operation-node/operation-node.ts @@ -80,6 +80,18 @@ export type OperationNodeKind = | 'FunctionNode' | 'CaseNode' | 'WhenNode' + | 'JSONReferenceNode' + | 'JSONPathNode' + | 'JSONPathLegNode' + | 'JSONOperatorChainNode' + | 'TupleNode' + | 'MergeQueryNode' + | 'MatchedNode' + | 'AddIndexNode' + | 'CastNode' + | 'FetchNode' + | 'TopNode' + | 'OutputNode' export interface OperationNode { readonly kind: OperationNodeKind diff --git a/src/operation-node/operator-node.ts b/src/operation-node/operator-node.ts index 265905c9f..783658655 100644 --- a/src/operation-node/operator-node.ts +++ b/src/operation-node/operator-node.ts @@ -21,6 +21,7 @@ export const COMPARISON_OPERATORS = [ 'not ilike', '@>', '<@', + '&&', '?', '?&', '!<', @@ -34,6 +35,9 @@ export const COMPARISON_OPERATORS = [ '@@@', '!!', '<->', + 'regexp', + 'is distinct from', + 'is not distinct from', ] as const export const ARITHMETIC_OPERATORS = [ @@ -50,6 +54,8 @@ export const ARITHMETIC_OPERATORS = [ '>>', ] as const +export const JSON_OPERATORS = ['->', '->>'] as const + export const BINARY_OPERATORS = [ ...COMPARISON_OPERATORS, ...ARITHMETIC_OPERATORS, @@ -59,14 +65,22 @@ export const BINARY_OPERATORS = [ export const UNARY_FILTER_OPERATORS = ['exists', 'not exists'] as const export const UNARY_OPERATORS = ['not', '-', ...UNARY_FILTER_OPERATORS] as const -export const OPERATORS = [...BINARY_OPERATORS, ...UNARY_OPERATORS] as const +export const OPERATORS = [ + ...BINARY_OPERATORS, + ...JSON_OPERATORS, + ...UNARY_OPERATORS, + 'between', + 'between symmetric', +] as const -export type ComparisonOperator = typeof COMPARISON_OPERATORS[number] -export type ArithmeticOperator = typeof ARITHMETIC_OPERATORS[number] -export type BinaryOperator = typeof BINARY_OPERATORS[number] -export type UnaryOperator = typeof UNARY_OPERATORS[number] -export type UnaryFilterOperator = typeof UNARY_FILTER_OPERATORS[number] -export type Operator = typeof OPERATORS[number] +export type ComparisonOperator = (typeof COMPARISON_OPERATORS)[number] +export type ArithmeticOperator = (typeof ARITHMETIC_OPERATORS)[number] +export type JSONOperator = (typeof JSON_OPERATORS)[number] +export type JSONOperatorWith$ = JSONOperator | `${JSONOperator}$` +export type BinaryOperator = (typeof BINARY_OPERATORS)[number] +export type UnaryOperator = (typeof UNARY_OPERATORS)[number] +export type UnaryFilterOperator = (typeof UNARY_FILTER_OPERATORS)[number] +export type Operator = (typeof OPERATORS)[number] export interface OperatorNode extends OperationNode { readonly kind: 'OperatorNode' @@ -104,3 +118,7 @@ export function isComparisonOperator(op: unknown): op is ComparisonOperator { export function isArithmeticOperator(op: unknown): op is ArithmeticOperator { return isString(op) && ARITHMETIC_OPERATORS.includes(op as ArithmeticOperator) } + +export function isJSONOperator(op: unknown): op is JSONOperator { + return isString(op) && JSON_OPERATORS.includes(op as JSONOperator) +} diff --git a/src/operation-node/order-by-node.ts b/src/operation-node/order-by-node.ts index 9108ea2c6..0102d7a60 100644 --- a/src/operation-node/order-by-node.ts +++ b/src/operation-node/order-by-node.ts @@ -15,17 +15,20 @@ export const OrderByNode = freeze({ return node.kind === 'OrderByNode' }, - create(item: OrderByItemNode): OrderByNode { + create(items: ReadonlyArray): OrderByNode { return freeze({ kind: 'OrderByNode', - items: freeze([item]), + items: freeze([...items]), }) }, - cloneWithItem(orderBy: OrderByNode, item: OrderByItemNode): OrderByNode { + cloneWithItems( + orderBy: OrderByNode, + items: ReadonlyArray, + ): OrderByNode { return freeze({ ...orderBy, - items: freeze([...orderBy.items, item]), + items: freeze([...orderBy.items, ...items]), }) }, }) diff --git a/src/operation-node/output-node.ts b/src/operation-node/output-node.ts new file mode 100644 index 000000000..6f28c6b4b --- /dev/null +++ b/src/operation-node/output-node.ts @@ -0,0 +1,35 @@ +import { freeze } from '../util/object-utils.js' +import { OperationNode } from './operation-node.js' + +export interface OutputNode extends OperationNode { + readonly kind: 'OutputNode' + readonly selections: ReadonlyArray +} + +/** + * @internal + */ +export const OutputNode = freeze({ + is(node: OperationNode): node is OutputNode { + return node.kind === 'OutputNode' + }, + + create(selections: ReadonlyArray): OutputNode { + return freeze({ + kind: 'OutputNode', + selections: freeze(selections), + }) + }, + + cloneWithSelections( + output: OutputNode, + selections: ReadonlyArray + ): OutputNode { + return freeze({ + ...output, + selections: output.selections + ? freeze([...output.selections, ...selections]) + : freeze(selections), + }) + }, +}) diff --git a/src/operation-node/over-node.ts b/src/operation-node/over-node.ts index 325a20c76..239cb0865 100644 --- a/src/operation-node/over-node.ts +++ b/src/operation-node/over-node.ts @@ -25,18 +25,21 @@ export const OverNode = freeze({ }) }, - cloneWithOrderByItem(overNode: OverNode, item: OrderByItemNode): OverNode { + cloneWithOrderByItems( + overNode: OverNode, + items: ReadonlyArray, + ): OverNode { return freeze({ ...overNode, orderBy: overNode.orderBy - ? OrderByNode.cloneWithItem(overNode.orderBy, item) - : OrderByNode.create(item), + ? OrderByNode.cloneWithItems(overNode.orderBy, items) + : OrderByNode.create(items), }) }, cloneWithPartitionByItems( overNode: OverNode, - items: ReadonlyArray + items: ReadonlyArray, ): OverNode { return freeze({ ...overNode, diff --git a/src/operation-node/partition-by-node.ts b/src/operation-node/partition-by-node.ts index 25f522d5f..07a83a505 100644 --- a/src/operation-node/partition-by-node.ts +++ b/src/operation-node/partition-by-node.ts @@ -24,7 +24,7 @@ export const PartitionByNode = freeze({ cloneWithItems( partitionBy: PartitionByNode, - items: ReadonlyArray + items: ReadonlyArray, ): PartitionByNode { return freeze({ ...partitionBy, diff --git a/src/operation-node/query-node.ts b/src/operation-node/query-node.ts index d414e70ca..38cfdf995 100644 --- a/src/operation-node/query-node.ts +++ b/src/operation-node/query-node.ts @@ -11,17 +11,23 @@ import { OperationNode } from './operation-node.js' import { ExplainNode } from './explain-node.js' import { ExplainFormat } from '../util/explainable.js' import { Expression } from '../expression/expression.js' +import { MergeQueryNode } from './merge-query-node.js' +import { TopNode } from './top-node.js' +import { OutputNode } from './output-node.js' export type QueryNode = | SelectQueryNode | InsertQueryNode | UpdateQueryNode | DeleteQueryNode + | MergeQueryNode type HasJoins = { joins?: ReadonlyArray } type HasWhere = { where?: WhereNode } type HasReturning = { returning?: ReturningNode } type HasExplain = { explain?: ExplainNode } +type HasTop = { top?: TopNode } +type HasOutput = { output?: OutputNode } /** * @internal @@ -32,7 +38,8 @@ export const QueryNode = freeze({ SelectQueryNode.is(node) || InsertQueryNode.is(node) || UpdateQueryNode.is(node) || - DeleteQueryNode.is(node) + DeleteQueryNode.is(node) || + MergeQueryNode.is(node) ) }, @@ -45,15 +52,6 @@ export const QueryNode = freeze({ }) }, - cloneWithOrWhere(node: T, operation: OperationNode): T { - return freeze({ - ...node, - where: node.where - ? WhereNode.cloneWithOperation(node.where, 'Or', operation) - : WhereNode.create(operation), - }) - }, - cloneWithJoin(node: T, join: JoinNode): T { return freeze({ ...node, @@ -63,7 +61,7 @@ export const QueryNode = freeze({ cloneWithReturning( node: T, - selections: ReadonlyArray + selections: ReadonlyArray, ): T { return freeze({ ...node, @@ -73,6 +71,13 @@ export const QueryNode = freeze({ }) }, + cloneWithoutReturning(node: T): T { + return freeze({ + ...node, + returning: undefined, + }) + }, + cloneWithoutWhere(node: T): T { return freeze({ ...node, @@ -83,11 +88,30 @@ export const QueryNode = freeze({ cloneWithExplain( node: T, format: ExplainFormat | undefined, - options: Expression | undefined + options: Expression | undefined, ): T { return freeze({ ...node, explain: ExplainNode.create(format, options?.toOperationNode()), }) }, + + cloneWithTop(node: T, top: TopNode): T { + return freeze({ + ...node, + top, + }) + }, + + cloneWithOutput( + node: T, + selections: ReadonlyArray, + ): T { + return freeze({ + ...node, + output: node.output + ? OutputNode.cloneWithSelections(node.output, selections) + : OutputNode.create(selections), + }) + }, }) diff --git a/src/operation-node/raw-node.ts b/src/operation-node/raw-node.ts index c88cac10b..7821f3920 100644 --- a/src/operation-node/raw-node.ts +++ b/src/operation-node/raw-node.ts @@ -17,7 +17,7 @@ export const RawNode = freeze({ create( sqlFragments: ReadonlyArray, - parameters: ReadonlyArray + parameters: ReadonlyArray, ): RawNode { return freeze({ kind: 'RawNode', diff --git a/src/operation-node/reference-node.ts b/src/operation-node/reference-node.ts index 94b256cc0..eedb3b112 100644 --- a/src/operation-node/reference-node.ts +++ b/src/operation-node/reference-node.ts @@ -6,8 +6,8 @@ import { freeze } from '../util/object-utils.js' export interface ReferenceNode extends OperationNode { readonly kind: 'ReferenceNode' - readonly table: TableNode readonly column: ColumnNode | SelectAllNode + readonly table?: TableNode } /** @@ -18,7 +18,7 @@ export const ReferenceNode = freeze({ return node.kind === 'ReferenceNode' }, - create(table: TableNode, column: ColumnNode): ReferenceNode { + create(column: ColumnNode, table?: TableNode): ReferenceNode { return freeze({ kind: 'ReferenceNode', table, diff --git a/src/operation-node/references-node.ts b/src/operation-node/references-node.ts index b143e99fa..8dab08654 100644 --- a/src/operation-node/references-node.ts +++ b/src/operation-node/references-node.ts @@ -42,7 +42,7 @@ export const ReferencesNode = freeze({ cloneWithOnDelete( references: ReferencesNode, - onDelete: OnModifyForeignAction + onDelete: OnModifyForeignAction, ): ReferencesNode { return freeze({ ...references, @@ -52,7 +52,7 @@ export const ReferencesNode = freeze({ cloneWithOnUpdate( references: ReferencesNode, - onUpdate: OnModifyForeignAction + onUpdate: OnModifyForeignAction, ): ReferencesNode { return freeze({ ...references, diff --git a/src/operation-node/returning-node.ts b/src/operation-node/returning-node.ts index 1a0924aab..328970fa6 100644 --- a/src/operation-node/returning-node.ts +++ b/src/operation-node/returning-node.ts @@ -24,7 +24,7 @@ export const ReturningNode = freeze({ cloneWithSelections( returning: ReturningNode, - selections: ReadonlyArray + selections: ReadonlyArray, ): ReturningNode { return freeze({ ...returning, diff --git a/src/operation-node/schemable-identifier-node.ts b/src/operation-node/schemable-identifier-node.ts index a29ca3ebf..c0980a4e8 100644 --- a/src/operation-node/schemable-identifier-node.ts +++ b/src/operation-node/schemable-identifier-node.ts @@ -25,7 +25,7 @@ export const SchemableIdentifierNode = freeze({ createWithSchema( schema: string, - identifier: string + identifier: string, ): SchemableIdentifierNode { return freeze({ kind: 'SchemableIdentifierNode', diff --git a/src/operation-node/select-modifier-node.ts b/src/operation-node/select-modifier-node.ts index fa6a6f474..353eca0e9 100644 --- a/src/operation-node/select-modifier-node.ts +++ b/src/operation-node/select-modifier-node.ts @@ -14,6 +14,7 @@ export interface SelectModifierNode extends OperationNode { readonly kind: 'SelectModifierNode' readonly modifier?: SelectModifier readonly rawModifier?: OperationNode + readonly of?: ReadonlyArray } /** @@ -24,10 +25,14 @@ export const SelectModifierNode = freeze({ return node.kind === 'SelectModifierNode' }, - create(modifier: SelectModifier): SelectModifierNode { + create( + modifier: SelectModifier, + of?: ReadonlyArray, + ): SelectModifierNode { return freeze({ kind: 'SelectModifierNode', modifier, + of, }) }, diff --git a/src/operation-node/select-query-node.ts b/src/operation-node/select-query-node.ts index 712e062b7..aac84ce41 100644 --- a/src/operation-node/select-query-node.ts +++ b/src/operation-node/select-query-node.ts @@ -15,10 +15,12 @@ import { WithNode } from './with-node.js' import { SelectModifierNode } from './select-modifier-node.js' import { ExplainNode } from './explain-node.js' import { SetOperationNode } from './set-operation-node.js' +import { FetchNode } from './fetch-node.js' +import { TopNode } from './top-node.js' export interface SelectQueryNode extends OperationNode { readonly kind: 'SelectQueryNode' - readonly from: FromNode + readonly from?: FromNode readonly selections?: ReadonlyArray readonly distinctOn?: ReadonlyArray readonly joins?: ReadonlyArray @@ -33,6 +35,8 @@ export interface SelectQueryNode extends OperationNode { readonly having?: HavingNode readonly explain?: ExplainNode readonly setOperations?: ReadonlyArray + readonly fetch?: FetchNode + readonly top?: TopNode } /** @@ -43,9 +47,16 @@ export const SelectQueryNode = freeze({ return node.kind === 'SelectQueryNode' }, - create( + create(withNode?: WithNode): SelectQueryNode { + return freeze({ + kind: 'SelectQueryNode', + ...(withNode && { with: withNode }), + }) + }, + + createFrom( fromItems: ReadonlyArray, - withNode?: WithNode + withNode?: WithNode, ): SelectQueryNode { return freeze({ kind: 'SelectQueryNode', @@ -56,7 +67,7 @@ export const SelectQueryNode = freeze({ cloneWithSelections( select: SelectQueryNode, - selections: ReadonlyArray + selections: ReadonlyArray, ): SelectQueryNode { return freeze({ ...select, @@ -68,7 +79,7 @@ export const SelectQueryNode = freeze({ cloneWithDistinctOn( select: SelectQueryNode, - expressions: ReadonlyArray + expressions: ReadonlyArray, ): SelectQueryNode { return freeze({ ...select, @@ -80,7 +91,7 @@ export const SelectQueryNode = freeze({ cloneWithFrontModifier( select: SelectQueryNode, - modifier: SelectModifierNode + modifier: SelectModifierNode, ): SelectQueryNode { return freeze({ ...select, @@ -92,7 +103,7 @@ export const SelectQueryNode = freeze({ cloneWithEndModifier( select: SelectQueryNode, - modifier: SelectModifierNode + modifier: SelectModifierNode, ): SelectQueryNode { return freeze({ ...select, @@ -102,21 +113,21 @@ export const SelectQueryNode = freeze({ }) }, - cloneWithOrderByItem( + cloneWithOrderByItems( selectNode: SelectQueryNode, - item: OrderByItemNode + items: ReadonlyArray, ): SelectQueryNode { return freeze({ ...selectNode, orderBy: selectNode.orderBy - ? OrderByNode.cloneWithItem(selectNode.orderBy, item) - : OrderByNode.create(item), + ? OrderByNode.cloneWithItems(selectNode.orderBy, items) + : OrderByNode.create(items), }) }, cloneWithGroupByItems( selectNode: SelectQueryNode, - items: ReadonlyArray + items: ReadonlyArray, ): SelectQueryNode { return freeze({ ...selectNode, @@ -128,7 +139,7 @@ export const SelectQueryNode = freeze({ cloneWithLimit( selectNode: SelectQueryNode, - limit: LimitNode + limit: LimitNode, ): SelectQueryNode { return freeze({ ...selectNode, @@ -138,7 +149,7 @@ export const SelectQueryNode = freeze({ cloneWithOffset( selectNode: SelectQueryNode, - offset: OffsetNode + offset: OffsetNode, ): SelectQueryNode { return freeze({ ...selectNode, @@ -146,39 +157,37 @@ export const SelectQueryNode = freeze({ }) }, - cloneWithHaving( + cloneWithFetch( selectNode: SelectQueryNode, - operation: OperationNode + fetch: FetchNode ): SelectQueryNode { return freeze({ ...selectNode, - having: selectNode.having - ? HavingNode.cloneWithOperation(selectNode.having, 'And', operation) - : HavingNode.create(operation), + fetch, }) }, - cloneWithOrHaving( + cloneWithHaving( selectNode: SelectQueryNode, - operation: OperationNode + operation: OperationNode, ): SelectQueryNode { return freeze({ ...selectNode, having: selectNode.having - ? HavingNode.cloneWithOperation(selectNode.having, 'Or', operation) + ? HavingNode.cloneWithOperation(selectNode.having, 'And', operation) : HavingNode.create(operation), }) }, - cloneWithSetOperation( + cloneWithSetOperations( selectNode: SelectQueryNode, - setOperation: SetOperationNode + setOperations: ReadonlyArray, ): SelectQueryNode { return freeze({ ...selectNode, setOperations: selectNode.setOperations - ? freeze([...selectNode.setOperations, setOperation]) - : freeze([setOperation]), + ? freeze([...selectNode.setOperations, ...setOperations]) + : freeze([...setOperations]), }) }, @@ -209,4 +218,11 @@ export const SelectQueryNode = freeze({ orderBy: undefined, }) }, + + cloneWithoutGroupBy(select: SelectQueryNode): SelectQueryNode { + return freeze({ + ...select, + groupBy: undefined, + }) + }, }) diff --git a/src/operation-node/set-operation-node.ts b/src/operation-node/set-operation-node.ts index e4abb5515..ec0ff767f 100644 --- a/src/operation-node/set-operation-node.ts +++ b/src/operation-node/set-operation-node.ts @@ -21,7 +21,7 @@ export const SetOperationNode = freeze({ create( operator: SetOperator, expression: OperationNode, - all: boolean + all: boolean, ): SetOperationNode { return freeze({ kind: 'SetOperationNode', diff --git a/src/operation-node/top-node.ts b/src/operation-node/top-node.ts new file mode 100644 index 000000000..06692611f --- /dev/null +++ b/src/operation-node/top-node.ts @@ -0,0 +1,27 @@ +import { freeze } from '../util/object-utils.js' +import { OperationNode } from './operation-node.js' + +export type TopModifier = 'percent' | 'with ties' | 'percent with ties' + +export interface TopNode extends OperationNode { + readonly kind: 'TopNode' + readonly expression: number | bigint + readonly modifiers?: TopModifier +} + +/** + * @internal + */ +export const TopNode = freeze({ + is(node: OperationNode): node is TopNode { + return node.kind === 'TopNode' + }, + + create(expression: number | bigint, modifiers?: TopModifier): TopNode { + return freeze({ + kind: 'TopNode', + expression, + modifiers, + }) + }, +}) diff --git a/src/operation-node/tuple-node.ts b/src/operation-node/tuple-node.ts new file mode 100644 index 000000000..bb4ae261f --- /dev/null +++ b/src/operation-node/tuple-node.ts @@ -0,0 +1,23 @@ +import { freeze } from '../util/object-utils.js' +import { OperationNode } from './operation-node.js' + +export interface TupleNode extends OperationNode { + readonly kind: 'TupleNode' + readonly values: ReadonlyArray +} + +/** + * @internal + */ +export const TupleNode = freeze({ + is(node: OperationNode): node is TupleNode { + return node.kind === 'TupleNode' + }, + + create(values: ReadonlyArray): TupleNode { + return freeze({ + kind: 'TupleNode', + values: freeze(values), + }) + }, +}) diff --git a/src/operation-node/unique-constraint-node.ts b/src/operation-node/unique-constraint-node.ts index 29d069cd0..ef7bb1b0c 100644 --- a/src/operation-node/unique-constraint-node.ts +++ b/src/operation-node/unique-constraint-node.ts @@ -7,8 +7,14 @@ export interface UniqueConstraintNode extends OperationNode { readonly kind: 'UniqueConstraintNode' readonly columns: ReadonlyArray readonly name?: IdentifierNode + readonly nullsNotDistinct?: boolean } +export type UniqueConstraintNodeProps = Omit< + Partial, + 'kind' +> + /** * @internal */ @@ -17,11 +23,26 @@ export const UniqueConstraintNode = freeze({ return node.kind === 'UniqueConstraintNode' }, - create(columns: string[], constraintName?: string): UniqueConstraintNode { + create( + columns: string[], + constraintName?: string, + nullsNotDistinct?: boolean, + ): UniqueConstraintNode { return freeze({ kind: 'UniqueConstraintNode', columns: freeze(columns.map(ColumnNode.create)), name: constraintName ? IdentifierNode.create(constraintName) : undefined, + nullsNotDistinct, + }) + }, + + cloneWith( + node: UniqueConstraintNode, + props: UniqueConstraintNodeProps, + ): UniqueConstraintNode { + return freeze({ + ...node, + ...props, }) }, }) diff --git a/src/operation-node/update-query-node.ts b/src/operation-node/update-query-node.ts index d249c8cc0..82d4b842a 100644 --- a/src/operation-node/update-query-node.ts +++ b/src/operation-node/update-query-node.ts @@ -9,12 +9,15 @@ import { WhereNode } from './where-node.js' import { WithNode } from './with-node.js' import { FromNode } from './from-node.js' import { ExplainNode } from './explain-node.js' +import { LimitNode } from './limit-node.js' +import { TopNode } from './top-node.js' +import { OutputNode } from './output-node.js' export type UpdateValuesNode = ValueListNode | PrimitiveValueListNode export interface UpdateQueryNode extends OperationNode { readonly kind: 'UpdateQueryNode' - readonly table: OperationNode + readonly table?: OperationNode readonly from?: FromNode readonly joins?: ReadonlyArray readonly where?: WhereNode @@ -22,6 +25,9 @@ export interface UpdateQueryNode extends OperationNode { readonly returning?: ReturningNode readonly with?: WithNode readonly explain?: ExplainNode + readonly limit?: LimitNode + readonly top?: TopNode + readonly output?: OutputNode } /** @@ -40,9 +46,15 @@ export const UpdateQueryNode = freeze({ }) }, + createWithoutTable(): UpdateQueryNode { + return freeze({ + kind: 'UpdateQueryNode', + }) + }, + cloneWithFromItems( updateQuery: UpdateQueryNode, - fromItems: ReadonlyArray + fromItems: ReadonlyArray, ): UpdateQueryNode { return freeze({ ...updateQuery, @@ -54,7 +66,7 @@ export const UpdateQueryNode = freeze({ cloneWithUpdates( updateQuery: UpdateQueryNode, - updates: ReadonlyArray + updates: ReadonlyArray, ): UpdateQueryNode { return freeze({ ...updateQuery, @@ -63,4 +75,14 @@ export const UpdateQueryNode = freeze({ : updates, }) }, + + cloneWithLimit( + updateQuery: UpdateQueryNode, + limit: LimitNode, + ): UpdateQueryNode { + return freeze({ + ...updateQuery, + limit, + }) + }, }) diff --git a/src/operation-node/using-node.ts b/src/operation-node/using-node.ts index cdef79798..fa4777ebc 100644 --- a/src/operation-node/using-node.ts +++ b/src/operation-node/using-node.ts @@ -23,7 +23,7 @@ export const UsingNode = freeze({ cloneWithTables( using: UsingNode, - tables: ReadonlyArray + tables: ReadonlyArray, ): UsingNode { return freeze({ ...using, diff --git a/src/operation-node/where-node.ts b/src/operation-node/where-node.ts index 3b3953b94..01d39ce9f 100644 --- a/src/operation-node/where-node.ts +++ b/src/operation-node/where-node.ts @@ -26,7 +26,7 @@ export const WhereNode = freeze({ cloneWithOperation( whereNode: WhereNode, operator: 'And' | 'Or', - operation: OperationNode + operation: OperationNode, ): WhereNode { return freeze({ ...whereNode, diff --git a/src/operation-node/with-node.ts b/src/operation-node/with-node.ts index 00c2bfdb6..fe22adc15 100644 --- a/src/operation-node/with-node.ts +++ b/src/operation-node/with-node.ts @@ -20,7 +20,7 @@ export const WithNode = freeze({ create( expression: CommonTableExpressionNode, - params?: WithNodeParams + params?: WithNodeParams, ): WithNode { return freeze({ kind: 'WithNode', @@ -31,7 +31,7 @@ export const WithNode = freeze({ cloneWithExpression( withNode: WithNode, - expression: CommonTableExpressionNode + expression: CommonTableExpressionNode, ): WithNode { return freeze({ ...withNode, diff --git a/src/parser/binary-operation-parser.ts b/src/parser/binary-operation-parser.ts index 840c5aaa5..0346f48a1 100644 --- a/src/parser/binary-operation-parser.ts +++ b/src/parser/binary-operation-parser.ts @@ -1,57 +1,54 @@ import { BinaryOperationNode } from '../operation-node/binary-operation-node.js' import { - freeze, isBoolean, - isFunction, isNull, isString, + isUndefined, } from '../util/object-utils.js' -import { isOperationNodeSource } from '../operation-node/operation-node-source.js' -import { RawNode } from '../operation-node/raw-node.js' +import { + OperationNodeSource, + isOperationNodeSource, +} from '../operation-node/operation-node-source.js' import { OperatorNode, ComparisonOperator, - ArithmeticOperator, BinaryOperator, Operator, - isComparisonOperator, - isBinaryOperator, OPERATORS, } from '../operation-node/operator-node.js' -import { ParensNode } from '../operation-node/parens-node.js' import { ExtractTypeFromReferenceExpression, + ExtractTypeFromStringReference, parseReferenceExpression, ReferenceExpression, + StringReference, } from './reference-parser.js' import { + parseValueExpression, parseValueExpressionOrList, ValueExpression, ValueExpressionOrList, } from './value-parser.js' -import { JoinBuilder } from '../query-builder/join-builder.js' import { ValueNode } from '../operation-node/value-node.js' -import { WhereExpressionFactory } from '../query-builder/where-interface.js' -import { HavingExpressionFactory } from '../query-builder/having-interface.js' -import { createJoinBuilder, createSelectQueryBuilder } from './parse-utils.js' import { OperationNode } from '../operation-node/operation-node.js' import { Expression } from '../expression/expression.js' -import { SelectQueryNode } from '../operation-node/select-query-node.js' -import { JoinNode } from '../operation-node/join-node.js' -import { expressionBuilder } from '../expression/expression-builder.js' -import { UnaryOperationNode } from '../operation-node/unary-operation-node.js' -import { CaseNode } from '../operation-node/case-node.js' +import { SelectType } from '../util/column-type.js' +import { AndNode } from '../operation-node/and-node.js' +import { ParensNode } from '../operation-node/parens-node.js' +import { OrNode } from '../operation-node/or-node.js' +import { WhenNode } from '../operation-node/when-node.js' +import { RawNode } from '../operation-node/raw-node.js' export type OperandValueExpression< DB, TB extends keyof DB, - RE + RE, > = ValueExpression> export type OperandValueExpressionOrList< DB, TB extends keyof DB, - RE + RE, > = ValueExpressionOrList< DB, TB, @@ -65,120 +62,108 @@ export type ComparisonOperatorExpression = | ComparisonOperator | Expression -export type ArithmeticOperatorExpression = - | ArithmeticOperator - | Expression +export type FilterObject = { + [R in StringReference]?: ValueExpressionOrList< + DB, + TB, + SelectType> + > +} -type FilterExpressionType = 'where' | 'having' | 'on' | 'when' +export function parseValueBinaryOperationOrExpression( + args: any[], +): OperationNode { + if (args.length === 3) { + return parseValueBinaryOperation(args[0], args[1], args[2]) + } else if (args.length === 1) { + return parseValueExpression(args[0]) + } + + throw new Error(`invalid arguments: ${JSON.stringify(args)}`) +} export function parseValueBinaryOperation( - leftOperand: ReferenceExpression, + left: ReferenceExpression, operator: BinaryOperatorExpression, - rightOperand: OperandValueExpressionOrList + right: OperandValueExpressionOrList, ): BinaryOperationNode { - if (!isBinaryOperator(operator) && !isOperationNodeSource(operator)) { - throw new Error(`invalid binary operator ${JSON.stringify(operator)}`) - } - - if (isIsComparison(operator, rightOperand)) { - return parseIs(leftOperand, operator, rightOperand) + if (isIsOperator(operator) && needsIsOperator(right)) { + return BinaryOperationNode.create( + parseReferenceExpression(left), + parseOperator(operator), + ValueNode.createImmediate(right), + ) } return BinaryOperationNode.create( - parseReferenceExpression(leftOperand), + parseReferenceExpression(left), parseOperator(operator), - parseValueExpressionOrList(rightOperand) + parseValueExpressionOrList(right), ) } export function parseReferentialBinaryOperation( - leftOperand: ReferenceExpression, + left: ReferenceExpression, operator: BinaryOperatorExpression, - rightOperand: OperandValueExpressionOrList + right: OperandValueExpressionOrList, ): BinaryOperationNode { - if (!isBinaryOperator(operator) && !isOperationNodeSource(operator)) { - throw new Error(`invalid binary operator ${JSON.stringify(operator)}`) - } - return BinaryOperationNode.create( - parseReferenceExpression(leftOperand), + parseReferenceExpression(left), parseOperator(operator), - parseReferenceExpression(rightOperand) + parseReferenceExpression(right), ) } -export function parseValueComparison( - leftOperand: ReferenceExpression, - operator: ComparisonOperatorExpression, - rightOperand: OperandValueExpressionOrList -): BinaryOperationNode { - if (!isComparisonOperator(operator) && !isOperationNodeSource(operator)) { - throw new Error(`invalid comparison operator ${JSON.stringify(operator)}`) - } - - return parseValueBinaryOperation(leftOperand, operator, rightOperand) +export function parseFilterObject( + obj: Readonly>, + combinator: 'and' | 'or', +): OperationNode { + return parseFilterList( + Object.entries(obj) + .filter(([, v]) => !isUndefined(v)) + .map(([k, v]) => + parseValueBinaryOperation(k, needsIsOperator(v) ? 'is' : '=', v), + ), + combinator, + ) } -export function parseReferentialComparison( - leftOperand: ReferenceExpression, - operator: ComparisonOperatorExpression, - rightOperand: ReferenceExpression -): BinaryOperationNode { - if (!isComparisonOperator(operator) && !isOperationNodeSource(operator)) { - throw new Error(`invalid comparison operator ${JSON.stringify(operator)}`) +export function parseFilterList( + list: ReadonlyArray, + combinator: 'and' | 'or', + withParens = true, +): OperationNode { + const combine = combinator === 'and' ? AndNode.create : OrNode.create + + if (list.length === 0) { + return BinaryOperationNode.create( + ValueNode.createImmediate(1), + OperatorNode.create('='), + ValueNode.createImmediate(combinator === 'and' ? 1 : 0), + ) } - return parseReferentialBinaryOperation(leftOperand, operator, rightOperand) -} - -export function parseWhere(args: any[]): OperationNode { - return parseFilter('where', args) -} - -export function parseHaving(args: any[]): OperationNode { - return parseFilter('having', args) -} - -export function parseOn(args: any[]): OperationNode { - return parseFilter('on', args) -} - -export function parseWhen(args: any[]): OperationNode { - return parseFilter('when', args) -} + let node = toOperationNode(list[0]) -function parseFilter(type: FilterExpressionType, args: any[]): OperationNode { - if (args.length === 3) { - return parseValueComparison(args[0], args[1], args[2]) + for (let i = 1; i < list.length; ++i) { + node = combine(node, toOperationNode(list[i])) } - if (args.length === 1) { - return parseOneArgFilterExpression(type, args[0]) + if (list.length > 1 && withParens) { + return ParensNode.create(node) } - throw createFilterExpressionError(type, args) + return node } -function isIsComparison( +function isIsOperator( operator: BinaryOperatorExpression, - rightOperand: OperandValueExpressionOrList ): operator is 'is' | 'is not' { - return ( - (operator === 'is' || operator === 'is not') && - (isNull(rightOperand) || isBoolean(rightOperand)) - ) + return operator === 'is' || operator === 'is not' } -function parseIs( - leftOperand: ReferenceExpression, - operator: 'is' | 'is not', - rightOperand: null | boolean -) { - return BinaryOperationNode.create( - parseReferenceExpression(leftOperand), - parseOperator(operator), - ValueNode.createImmediate(rightOperand) - ) +function needsIsOperator(value: unknown): value is null | boolean { + return isNull(value) || isBoolean(value) } function parseOperator(operator: OperatorExpression): OperationNode { @@ -193,101 +178,10 @@ function parseOperator(operator: OperatorExpression): OperationNode { throw new Error(`invalid operator ${JSON.stringify(operator)}`) } -function parseOneArgFilterExpression( - type: FilterExpressionType, - arg: any +function toOperationNode( + nodeOrSource: OperationNode | OperationNodeSource, ): OperationNode { - if (isFunction(arg)) { - if (type === 'when') { - throw new Error(`when method doesn't accept a callback as an argument`) - } - - return CALLBACK_PARSERS[type](arg) - } else if (isOperationNodeSource(arg)) { - const node = arg.toOperationNode() - - if ( - RawNode.is(node) || - BinaryOperationNode.is(node) || - UnaryOperationNode.is(node) || - ParensNode.is(node) || - CaseNode.is(node) - ) { - return node - } - } else if (type === 'when') { - return ValueNode.create(arg) - } - - throw createFilterExpressionError(type, arg) -} - -function createFilterExpressionError( - type: FilterExpressionType, - args: any[] -): Error { - return new Error( - `invalid arguments passed to a '${type}' method: ${JSON.stringify(args)}` - ) + return isOperationNodeSource(nodeOrSource) + ? nodeOrSource.toOperationNode() + : nodeOrSource } - -const CALLBACK_PARSERS = freeze({ - where(callback: WhereExpressionFactory): OperationNode { - // TODO: Remove this once the grouper overload is removed. - const whereBuilder = createSelectQueryBuilder() - const exprBuilder = expressionBuilder() - - const res = callback(Object.assign(whereBuilder, exprBuilder) as any) - const node = res.toOperationNode() - - if (SelectQueryNode.is(node)) { - if (!node.where) { - throw new Error('no `where` methods called inside a group callback') - } - - return ParensNode.create(node.where.where) - } else { - return node - } - }, - - having(callback: HavingExpressionFactory): OperationNode { - // TODO: Remove this once the grouper overload is removed. - const havingBuilder = createSelectQueryBuilder() - const exprBuilder = expressionBuilder() - - const res = callback(Object.assign(havingBuilder, exprBuilder) as any) - const node = res.toOperationNode() - - if (SelectQueryNode.is(node)) { - if (!node.having) { - throw new Error('no `having` methods called inside a group callback') - } - - return ParensNode.create(node.having.having) - } else { - return node - } - }, - - on( - callback: (qb: JoinBuilder) => JoinBuilder - ): OperationNode { - // TODO: Remove this once the grouper overload is removed. - const onBuilder = createJoinBuilder('InnerJoin', 'table') - const exprBuilder = expressionBuilder() - - const res = callback(Object.assign(onBuilder, exprBuilder) as any) - const node = res.toOperationNode() - - if (JoinNode.is(node)) { - if (!node.on) { - throw new Error('no `on` methods called inside a group callback') - } - - return ParensNode.create(node.on.on) - } else { - return node - } - }, -}) diff --git a/src/parser/coalesce-parser.ts b/src/parser/coalesce-parser.ts index 77f66d3bd..653284b01 100644 --- a/src/parser/coalesce-parser.ts +++ b/src/parser/coalesce-parser.ts @@ -1,24 +1,97 @@ -import { - ExtractTypeFromReferenceExpression, - ReferenceExpression, -} from './reference-parser.js' +import { ExtractTypeFromReferenceExpression } from './reference-parser.js' -export type CoalesceReferenceExpressionList< +export type ExtractTypeFromCoalesce1< DB, TB extends keyof DB, - RE extends unknown[], - O = never -> = RE extends [] - ? O - : RE extends [infer L, ...infer R] - ? L extends ReferenceExpression - ? null extends ExtractTypeFromReferenceExpression - ? CoalesceReferenceExpressionList< - DB, - TB, - R extends ReferenceExpression[] ? R : never, - O | ExtractTypeFromReferenceExpression - > - : Exclude | ExtractTypeFromReferenceExpression - : never - : never + R1, +> = ExtractTypeFromReferenceExpression + +export type ExtractTypeFromCoalesce2< + DB, + TB extends keyof DB, + R1, + R2, +> = ExtractTypeFromCoalesceValues2< + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression +> + +type ExtractTypeFromCoalesceValues2 = null extends V1 + ? null extends V2 + ? V1 | V2 + : NotNull + : NotNull + +export type ExtractTypeFromCoalesce3< + DB, + TB extends keyof DB, + R1, + R2, + R3, +> = ExtractTypeFromCoalesceValues3< + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression +> + +type ExtractTypeFromCoalesceValues3 = null extends V1 + ? null extends V2 + ? null extends V3 + ? V1 | V2 | V3 + : NotNull + : NotNull + : NotNull + +export type ExtractTypeFromCoalesce4< + DB, + TB extends keyof DB, + R1, + R2, + R3, + R4, +> = ExtractTypeFromCoalesceValues4< + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression +> + +type ExtractTypeFromCoalesceValues4 = null extends V1 + ? null extends V2 + ? null extends V3 + ? null extends V4 + ? V1 | V2 | V3 | V4 + : NotNull + : NotNull + : NotNull + : NotNull + +export type ExtractTypeFromCoalesce5< + DB, + TB extends keyof DB, + R1, + R2, + R3, + R4, + R5, +> = ExtractTypeFromCoalesceValues5< + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression +> + +type ExtractTypeFromCoalesceValues5 = null extends V1 + ? null extends V2 + ? null extends V3 + ? null extends V4 + ? null extends V5 + ? V1 | V2 | V3 | V4 | V5 + : NotNull + : NotNull + : NotNull + : NotNull + : NotNull + +type NotNull = Exclude diff --git a/src/parser/data-type-parser.ts b/src/parser/data-type-parser.ts index 45fe7af78..37bfb85ab 100644 --- a/src/parser/data-type-parser.ts +++ b/src/parser/data-type-parser.ts @@ -2,6 +2,7 @@ import { Expression } from '../expression/expression.js' import { ColumnDataType, DataTypeNode, + isColumnDataType, } from '../operation-node/data-type-node.js' import { isOperationNodeSource } from '../operation-node/operation-node-source.js' import { OperationNode } from '../operation-node/operation-node.js' @@ -9,9 +10,15 @@ import { OperationNode } from '../operation-node/operation-node.js' export type DataTypeExpression = ColumnDataType | Expression export function parseDataTypeExpression( - dataType: DataTypeExpression + dataType: DataTypeExpression, ): OperationNode { - return isOperationNodeSource(dataType) - ? dataType.toOperationNode() - : DataTypeNode.create(dataType) + if (isOperationNodeSource(dataType)) { + return dataType.toOperationNode() + } + + if (isColumnDataType(dataType)) { + return DataTypeNode.create(dataType) + } + + throw new Error(`invalid column data type ${JSON.stringify(dataType)}`) } diff --git a/src/parser/default-value-parser.ts b/src/parser/default-value-parser.ts index 656b73cbf..2bae52e22 100644 --- a/src/parser/default-value-parser.ts +++ b/src/parser/default-value-parser.ts @@ -6,7 +6,7 @@ import { ValueNode } from '../operation-node/value-node.js' export type DefaultValueExpression = unknown | Expression export function parseDefaultValueExpression( - value: DefaultValueExpression + value: DefaultValueExpression, ): OperationNode { return isOperationNodeSource(value) ? value.toOperationNode() diff --git a/src/parser/expression-parser.ts b/src/parser/expression-parser.ts index 9733ae6a6..c72ef38bc 100644 --- a/src/parser/expression-parser.ts +++ b/src/parser/expression-parser.ts @@ -11,38 +11,43 @@ import { expressionBuilder, ExpressionBuilder, } from '../expression/expression-builder.js' -import { SelectQueryBuilder } from '../query-builder/select-query-builder.js' +import { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js' import { isFunction } from '../util/object-utils.js' -import { ShallowRecord } from '../util/type-utils.js' -export type ExpressionOrFactory = +/** + * Like `Expression` but also accepts a select query with an output + * type extending `Record`. This type is useful because SQL + * treats records with a single column as single values. + */ +export type OperandExpression = // SQL treats a subquery with a single selection as a scalar. That's // why we need to explicitly allow `SelectQueryBuilder` here with a - // `ShallowRecord` output type, even though `SelectQueryBuilder` + // `Record` output type, even though `SelectQueryBuilder` // is also an `Expression`. - | SelectQueryBuilder> - | SelectQueryBuilderFactory> - | Expression - | ExpressionFactory + Expression | SelectQueryBuilderExpression> + +export type ExpressionOrFactory = + | OperandExpression + | OperandExpressionFactory export type AliasedExpressionOrFactory = | AliasedExpression | AliasedExpressionFactory -type SelectQueryBuilderFactory = ( - eb: ExpressionBuilder -) => SelectQueryBuilder - -type ExpressionFactory = ( - eb: ExpressionBuilder +export type ExpressionFactory = ( + eb: ExpressionBuilder, ) => Expression +type OperandExpressionFactory = ( + eb: ExpressionBuilder, +) => OperandExpression + type AliasedExpressionFactory = ( - eb: ExpressionBuilder + eb: ExpressionBuilder, ) => AliasedExpression export function parseExpression( - exp: ExpressionOrFactory + exp: ExpressionOrFactory, ): OperationNode { if (isOperationNodeSource(exp)) { return exp.toOperationNode() @@ -54,7 +59,7 @@ export function parseExpression( } export function parseAliasedExpression( - exp: AliasedExpressionOrFactory + exp: AliasedExpressionOrFactory, ): AliasNode { if (isOperationNodeSource(exp)) { return exp.toOperationNode() @@ -66,7 +71,7 @@ export function parseAliasedExpression( } export function isExpressionOrFactory( - obj: unknown + obj: unknown, ): obj is ExpressionOrFactory { return isExpression(obj) || isAliasedExpression(obj) || isFunction(obj) } diff --git a/src/parser/fetch-parser.ts b/src/parser/fetch-parser.ts new file mode 100644 index 000000000..79124ec6b --- /dev/null +++ b/src/parser/fetch-parser.ts @@ -0,0 +1,21 @@ +import { FetchModifier, FetchNode } from '../operation-node/fetch-node.js' +import { isBigInt, isNumber } from '../util/object-utils.js' + +export function parseFetch( + rowCount: number | bigint, + modifier: FetchModifier, +): FetchNode { + if (!isNumber(rowCount) && !isBigInt(rowCount)) { + throw new Error(`Invalid fetch row count: ${rowCount}`) + } + + if (!isFetchModifier(modifier)) { + throw new Error(`Invalid fetch modifier: ${modifier}`) + } + + return FetchNode.create(rowCount, modifier) +} + +function isFetchModifier(value: any): value is FetchModifier { + return value === 'only' || value === 'with ties' +} diff --git a/src/parser/group-by-parser.ts b/src/parser/group-by-parser.ts index 17d9bb0ae..5c5bcf7ed 100644 --- a/src/parser/group-by-parser.ts +++ b/src/parser/group-by-parser.ts @@ -17,11 +17,11 @@ export type GroupByArg = | GroupByExpression | ReadonlyArray> | (( - eb: ExpressionBuilder + eb: ExpressionBuilder, ) => ReadonlyArray>) export function parseGroupBy( - groupBy: GroupByArg + groupBy: GroupByArg, ): GroupByItemNode[] { groupBy = isFunction(groupBy) ? groupBy(expressionBuilder()) : groupBy return parseReferenceExpressionOrList(groupBy).map(GroupByItemNode.create) diff --git a/src/parser/insert-values-parser.ts b/src/parser/insert-values-parser.ts index ba37a293b..758b8cffd 100644 --- a/src/parser/insert-values-parser.ts +++ b/src/parser/insert-values-parser.ts @@ -37,16 +37,20 @@ export type InsertObjectOrList = | InsertObject | ReadonlyArray> -export type InsertObjectOrListFactory = ( - eb: ExpressionBuilder -) => InsertObjectOrList - -export type InsertExpression = - | InsertObjectOrList - | InsertObjectOrListFactory +export type InsertObjectOrListFactory< + DB, + TB extends keyof DB, + UT extends keyof DB = never, +> = (eb: ExpressionBuilder) => InsertObjectOrList + +export type InsertExpression< + DB, + TB extends keyof DB, + UT extends keyof DB = never, +> = InsertObjectOrList | InsertObjectOrListFactory export function parseInsertExpression( - arg: InsertExpression + arg: InsertExpression, ): [ReadonlyArray, ValuesNode] { const objectOrList = isFunction(arg) ? arg(expressionBuilder()) : arg const list = isReadonlyArray(objectOrList) @@ -57,7 +61,7 @@ export function parseInsertExpression( } function parseInsertColumnsAndValues( - rows: ReadonlyArray> + rows: ReadonlyArray>, ): [ReadonlyArray, ValuesNode] { const columns = parseColumnNamesAndIndexes(rows) @@ -68,7 +72,7 @@ function parseInsertColumnsAndValues( } function parseColumnNamesAndIndexes( - rows: ReadonlyArray> + rows: ReadonlyArray>, ): Map { const columns = new Map() @@ -87,7 +91,7 @@ function parseColumnNamesAndIndexes( function parseRowValues( row: InsertObject, - columns: Map + columns: Map, ): PrimitiveValueListNode | ValueListNode { const rowColumns = Object.keys(row) @@ -120,8 +124,8 @@ function parseRowValues( return ValueListNode.create( rowValues.map((it) => - isUndefined(it) ? defaultValue : parseValueExpression(it) - ) + isUndefined(it) ? defaultValue : parseValueExpression(it), + ), ) } diff --git a/src/parser/join-parser.ts b/src/parser/join-parser.ts index 4ef0cca37..981b80131 100644 --- a/src/parser/join-parser.ts +++ b/src/parser/join-parser.ts @@ -1,21 +1,29 @@ import { JoinNode, JoinType } from '../operation-node/join-node.js' -import { AnyColumn, AnyColumnWithTable } from '../util/type-utils.js' +import { + AnyColumn, + AnyColumnWithTable, + DrainOuterGeneric, +} from '../util/type-utils.js' import { TableExpression, parseTableExpression, From, FromTables, } from './table-parser.js' -import { parseReferentialComparison } from './binary-operation-parser.js' +import { parseReferentialBinaryOperation } from './binary-operation-parser.js' import { JoinBuilder } from '../query-builder/join-builder.js' import { createJoinBuilder } from './parse-utils.js' -export type JoinReferenceExpression = - | AnyJoinColumn - | AnyJoinColumnWithTable +export type JoinReferenceExpression< + DB, + TB extends keyof DB, + TE, +> = DrainOuterGeneric< + AnyJoinColumn | AnyJoinColumnWithTable +> export type JoinCallbackExpression = ( - join: JoinBuilder, FromTables> + join: JoinBuilder, FromTables>, ) => JoinBuilder type AnyJoinColumn = AnyColumn< @@ -41,21 +49,20 @@ export function parseJoin(joinType: JoinType, args: any[]): JoinNode { function parseCallbackJoin( joinType: JoinType, from: TableExpression, - callback: JoinCallbackExpression + callback: JoinCallbackExpression, ): JoinNode { - const joinBuilder = callback(createJoinBuilder(joinType, from)) - return joinBuilder.toOperationNode() + return callback(createJoinBuilder(joinType, from)).toOperationNode() } function parseSingleOnJoin( joinType: JoinType, from: TableExpression, lhsColumn: string, - rhsColumn: string + rhsColumn: string, ): JoinNode { return JoinNode.createWithOn( joinType, parseTableExpression(from), - parseReferentialComparison(lhsColumn, '=', rhsColumn) + parseReferentialBinaryOperation(lhsColumn, '=', rhsColumn), ) } diff --git a/src/parser/merge-parser.ts b/src/parser/merge-parser.ts new file mode 100644 index 000000000..56d383839 --- /dev/null +++ b/src/parser/merge-parser.ts @@ -0,0 +1,55 @@ +import { InsertQueryNode } from '../operation-node/insert-query-node.js' +import { MatchedNode } from '../operation-node/matched-node.js' +import { + OperationNodeSource, + isOperationNodeSource, +} from '../operation-node/operation-node-source.js' +import { OperationNode } from '../operation-node/operation-node.js' +import { RawNode } from '../operation-node/raw-node.js' +import { WhenNode } from '../operation-node/when-node.js' +import { isString } from '../util/object-utils.js' +import { + parseFilterList, + parseReferentialBinaryOperation, + parseValueBinaryOperationOrExpression, +} from './binary-operation-parser.js' + +export function parseMergeWhen( + type: { + isMatched: boolean + bySource?: boolean + }, + args?: any[], + refRight?: boolean, +): WhenNode { + return WhenNode.create( + parseFilterList( + [ + MatchedNode.create(!type.isMatched, type.bySource), + ...(args && args.length > 0 + ? [ + args.length === 3 && refRight + ? parseReferentialBinaryOperation(args[0], args[1], args[2]) + : parseValueBinaryOperationOrExpression(args), + ] + : []), + ], + 'and', + false, + ), + ) +} + +export function parseMergeThen( + result: 'delete' | 'do nothing' | OperationNodeSource | InsertQueryNode, +): OperationNode { + if (isString(result)) { + return RawNode.create([result], []) + } + + if (isOperationNodeSource(result)) { + return result.toOperationNode() + } + + return result +} diff --git a/src/parser/on-modify-action-parser.ts b/src/parser/on-modify-action-parser.ts index 3885f8b98..0345185ed 100644 --- a/src/parser/on-modify-action-parser.ts +++ b/src/parser/on-modify-action-parser.ts @@ -4,7 +4,7 @@ import { } from '../operation-node/references-node.js' export function parseOnModifyForeignAction( - action: OnModifyForeignAction + action: OnModifyForeignAction, ): OnModifyForeignAction { if (ON_MODIFY_FOREIGN_ACTIONS.includes(action)) { return action diff --git a/src/parser/order-by-parser.ts b/src/parser/order-by-parser.ts index a4566e3c8..cc2aeb704 100644 --- a/src/parser/order-by-parser.ts +++ b/src/parser/order-by-parser.ts @@ -1,11 +1,11 @@ +import { isDynamicReferenceBuilder } from '../dynamic/dynamic-reference-builder.js' import { Expression } from '../expression/expression.js' import { OperationNode } from '../operation-node/operation-node.js' import { OrderByItemNode } from '../operation-node/order-by-item-node.js' import { RawNode } from '../operation-node/raw-node.js' -import { - parseReferenceExpression, - ReferenceExpression, -} from './reference-parser.js' +import { isExpressionOrFactory, parseExpression } from './expression-parser.js' +import { StringReference, parseStringReference } from './reference-parser.js' +import { ReferenceExpression } from './reference-parser.js' export type OrderByDirection = 'asc' | 'desc' @@ -13,30 +13,89 @@ export function isOrderByDirection(thing: unknown): thing is OrderByDirection { return thing === 'asc' || thing === 'desc' } -export type OrderByExpression = +export type DirectedOrderByStringReference = `${ + | StringReference + | (keyof O & string)} ${OrderByDirection}` + +export type UndirectedOrderByExpression = | ReferenceExpression | (keyof O & string) +export type OrderByExpression = + | UndirectedOrderByExpression + | DirectedOrderByStringReference + export type OrderByDirectionExpression = OrderByDirection | Expression -export function parseOrderBy( - orderBy: OrderByExpression, - direction?: OrderByDirectionExpression +export function parseOrderBy(args: any[]): OrderByItemNode[] { + if (args.length === 2) { + return [parseOrderByItem(args[0], args[1])] + } + + if (args.length === 1) { + const [orderBy] = args + + if (Array.isArray(orderBy)) { + return orderBy.map((item) => parseOrderByItem(item)) + } + + return [parseOrderByItem(orderBy)] + } + + throw new Error( + `Invalid number of arguments at order by! expected 1-2, received ${args.length}`, + ) +} + +export function parseOrderByItem( + ref: ReferenceExpression, + direction?: OrderByDirectionExpression, ): OrderByItemNode { + const parsedRef = parseOrderByExpression(ref) + + if (OrderByItemNode.is(parsedRef)) { + if (direction) { + throw new Error('Cannot specify direction twice!') + } + + return parsedRef + } + return OrderByItemNode.create( - parseOrderByExpression(orderBy), - parseOrderByDirectionExpression(direction) + parsedRef, + parseOrderByDirectionExpression(direction), ) } function parseOrderByExpression( - expr: OrderByExpression + expr: OrderByExpression, ): OperationNode { - return parseReferenceExpression(expr) + if (isExpressionOrFactory(expr)) { + return parseExpression(expr) + } + + if (isDynamicReferenceBuilder(expr)) { + return expr.toOperationNode() + } + + const [ref, direction] = expr.split(' ') + + if (direction) { + if (!isOrderByDirection(direction)) { + throw new Error(`Invalid order by direction: ${direction}`) + } + + return OrderByItemNode.create( + parseStringReference(ref), + parseOrderByDirectionExpression(direction as any), + ) + } + + return parseStringReference(expr) } function parseOrderByDirectionExpression( - expr?: OrderByDirectionExpression + expr?: OrderByDirectionExpression, ): OperationNode | undefined { if (!expr) { return undefined @@ -44,7 +103,7 @@ function parseOrderByDirectionExpression( if (expr === 'asc' || expr === 'desc') { return RawNode.createWithSql(expr) - } else { - return expr.toOperationNode() } + + return expr.toOperationNode() } diff --git a/src/parser/parse-utils.ts b/src/parser/parse-utils.ts index da565ff84..6494da547 100644 --- a/src/parser/parse-utils.ts +++ b/src/parser/parse-utils.ts @@ -3,7 +3,10 @@ import { OverNode } from '../operation-node/over-node.js' import { SelectQueryNode } from '../operation-node/select-query-node.js' import { JoinBuilder } from '../query-builder/join-builder.js' import { OverBuilder } from '../query-builder/over-builder.js' -import { SelectQueryBuilder } from '../query-builder/select-query-builder.js' +import { + SelectQueryBuilder, + createSelectQueryBuilder as newSelectQueryBuilder, +} from '../query-builder/select-query-builder.js' import { QueryCreator } from '../query-creator.js' import { NOOP_QUERY_EXECUTOR } from '../query-executor/noop-query-executor.js' import { createQueryId } from '../util/query-id.js' @@ -14,10 +17,10 @@ import { } from './table-parser.js' export function createSelectQueryBuilder(): SelectQueryBuilder { - return new SelectQueryBuilder({ + return newSelectQueryBuilder({ queryId: createQueryId(), executor: NOOP_QUERY_EXECUTOR, - queryNode: SelectQueryNode.create(parseTableExpressionOrList([])), + queryNode: SelectQueryNode.createFrom(parseTableExpressionOrList([])), }) } @@ -29,7 +32,7 @@ export function createQueryCreator(): QueryCreator { export function createJoinBuilder( joinType: JoinType, - table: TableExpression + table: TableExpression, ): JoinBuilder { return new JoinBuilder({ joinNode: JoinNode.create(joinType, parseTableExpression(table)), diff --git a/src/parser/partition-by-parser.ts b/src/parser/partition-by-parser.ts index 53e3813e0..33285ff5c 100644 --- a/src/parser/partition-by-parser.ts +++ b/src/parser/partition-by-parser.ts @@ -15,11 +15,11 @@ export type PartitionByExpressionOrList = | PartitionByExpression export function parsePartitionBy( - partitionBy: PartitionByExpressionOrList + partitionBy: PartitionByExpressionOrList, ): PartitionByItemNode[] { return ( parseReferenceExpressionOrList( - partitionBy + partitionBy, ) as SimpleReferenceExpressionNode[] ).map(PartitionByItemNode.create) } diff --git a/src/parser/reference-parser.ts b/src/parser/reference-parser.ts index f55574d00..15273172d 100644 --- a/src/parser/reference-parser.ts +++ b/src/parser/reference-parser.ts @@ -8,14 +8,14 @@ import { AnyColumnWithTable, ExtractColumnType, } from '../util/type-utils.js' -import { SelectQueryBuilder } from '../query-builder/select-query-builder.js' +import { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js' import { parseExpression, ExpressionOrFactory, isExpressionOrFactory, } from './expression-parser.js' import { DynamicReferenceBuilder } from '../dynamic/dynamic-reference-builder.js' -import { SelectType } from '../util/column-type.js' +import { SelectType, UpdateType } from '../util/column-type.js' import { IdentifierNode } from '../operation-node/identifier-node.js' import { OperationNode } from '../operation-node/operation-node.js' import { Expression } from '../expression/expression.js' @@ -25,6 +25,14 @@ import { isOrderByDirection, parseOrderBy, } from './order-by-parser.js' +import { + JSONOperatorWith$, + OperatorNode, + isJSONOperator, +} from '../operation-node/operator-node.js' +import { JSONReferenceNode } from '../operation-node/json-reference-node.js' +import { JSONOperatorChainNode } from '../operation-node/json-operator-chain-node.js' +import { JSONPathNode } from '../operation-node/json-path-node.js' export type StringReference = | AnyColumn @@ -46,24 +54,31 @@ export type ExtractTypeFromReferenceExpression< DB, TB extends keyof DB, RE, - DV = unknown + DV = unknown, +> = SelectType> + +export type ExtractRawTypeFromReferenceExpression< + DB, + TB extends keyof DB, + RE, + DV = unknown, > = RE extends string - ? SelectType> - : RE extends SelectQueryBuilder - ? O[keyof O] | null - : RE extends (qb: any) => SelectQueryBuilder - ? O[keyof O] | null - : RE extends Expression - ? O - : RE extends (qb: any) => Expression - ? O - : DV + ? ExtractTypeFromStringReference + : RE extends SelectQueryBuilderExpression + ? O[keyof O] | null + : RE extends (qb: any) => SelectQueryBuilderExpression + ? O[keyof O] | null + : RE extends Expression + ? O + : RE extends (qb: any) => Expression + ? O + : DV export type ExtractTypeFromStringReference< DB, TB extends keyof DB, RE extends string, - DV = unknown + DV = unknown, > = RE extends `${infer SC}.${infer T}.${infer C}` ? `${SC}.${T}` extends TB ? C extends keyof DB[`${SC}.${T}`] @@ -71,14 +86,14 @@ export type ExtractTypeFromStringReference< : never : never : RE extends `${infer T}.${infer C}` - ? T extends TB - ? C extends keyof DB[T] - ? DB[T][C] + ? T extends TB + ? C extends keyof DB[T] + ? DB[T][C] + : never : never - : never - : RE extends AnyColumn - ? ExtractColumnType - : DV + : RE extends AnyColumn + ? ExtractColumnType + : DV export type OrderedColumnName = C extends `${string} ${infer O}` @@ -95,7 +110,7 @@ export type ExtractColumnNameFromOrderedColumnName = : C export function parseSimpleReferenceExpression( - exp: SimpleReferenceExpression + exp: SimpleReferenceExpression, ): SimpleReferenceExpressionNode { if (isString(exp)) { return parseStringReference(exp) @@ -105,7 +120,7 @@ export function parseSimpleReferenceExpression( } export function parseReferenceExpressionOrList( - arg: ReferenceExpressionOrList + arg: ReferenceExpressionOrList, ): OperationNode[] { if (isReadonlyArray(arg)) { return arg.map((it) => parseReferenceExpression(it)) @@ -115,7 +130,7 @@ export function parseReferenceExpressionOrList( } export function parseReferenceExpression( - exp: ReferenceExpression + exp: ReferenceExpression, ): OperationNode { if (isExpressionOrFactory(exp)) { return parseExpression(exp) @@ -124,28 +139,53 @@ export function parseReferenceExpression( return parseSimpleReferenceExpression(exp) } -export function parseStringReference( - ref: string -): SimpleReferenceExpressionNode { +export function parseJSONReference( + ref: string, + op: JSONOperatorWith$, +): JSONReferenceNode { + const referenceNode = parseStringReference(ref) + + if (isJSONOperator(op)) { + return JSONReferenceNode.create( + referenceNode, + JSONOperatorChainNode.create(OperatorNode.create(op)), + ) + } + + const opWithoutLastChar = op.slice(0, -1) + + if (isJSONOperator(opWithoutLastChar)) { + return JSONReferenceNode.create( + referenceNode, + JSONPathNode.create(OperatorNode.create(opWithoutLastChar)), + ) + } + + throw new Error(`Invalid JSON operator: ${op}`) +} + +export function parseStringReference(ref: string): ReferenceNode { const COLUMN_SEPARATOR = '.' - if (ref.includes(COLUMN_SEPARATOR)) { - const parts = ref.split(COLUMN_SEPARATOR).map(trim) + if (!ref.includes(COLUMN_SEPARATOR)) { + return ReferenceNode.create(ColumnNode.create(ref)) + } + + const parts = ref.split(COLUMN_SEPARATOR).map(trim) - if (parts.length === 3) { - return parseStringReferenceWithTableAndSchema(parts) - } else if (parts.length === 2) { - return parseStringReferenceWithTable(parts) - } else { - throw new Error(`invalid column reference ${ref}`) - } - } else { - return ColumnNode.create(ref) + if (parts.length === 3) { + return parseStringReferenceWithTableAndSchema(parts) } + + if (parts.length === 2) { + return parseStringReferenceWithTable(parts) + } + + throw new Error(`invalid column reference ${ref}`) } export function parseAliasedStringReference( - ref: string + ref: string, ): SimpleReferenceExpressionNode | AliasNode { const ALIAS_SEPARATOR = ' as ' @@ -154,7 +194,7 @@ export function parseAliasedStringReference( return AliasNode.create( parseStringReference(columnRef), - IdentifierNode.create(alias) + IdentifierNode.create(alias), ) } else { return parseStringReference(ref) @@ -173,24 +213,24 @@ export function parseOrderedColumnName(column: string): OperationNode { if (!isOrderByDirection(order)) { throw new Error( - `invalid order direction "${order}" next to "${columnName}"` + `invalid order direction "${order}" next to "${columnName}"`, ) } - return parseOrderBy(columnName, order) + return parseOrderBy([columnName, order])[0] } else { return parseColumnName(column) } } function parseStringReferenceWithTableAndSchema( - parts: string[] + parts: string[], ): ReferenceNode { const [schema, table, column] = parts return ReferenceNode.create( + ColumnNode.create(column), TableNode.createWithSchema(schema, table), - ColumnNode.create(column) ) } @@ -198,8 +238,8 @@ function parseStringReferenceWithTable(parts: string[]): ReferenceNode { const [table, column] = parts return ReferenceNode.create( + ColumnNode.create(column), TableNode.create(table), - ColumnNode.create(column) ) } diff --git a/src/parser/returning-parser.ts b/src/parser/returning-parser.ts index abc0520a7..dac0eee72 100644 --- a/src/parser/returning-parser.ts +++ b/src/parser/returning-parser.ts @@ -1,25 +1,29 @@ import { DeleteResult } from '../query-builder/delete-result.js' import { InsertResult } from '../query-builder/insert-result.js' +import { MergeResult } from '../query-builder/merge-result.js' import { UpdateResult } from '../query-builder/update-result.js' -import { Selection, AllSelection } from './select-parser.js' +import { Selection, AllSelection, CallbackSelection } from './select-parser.js' -export type ReturningRow< - DB, - TB extends keyof DB, - O, - SE -> = O extends InsertResult - ? Selection - : O extends DeleteResult - ? Selection - : O extends UpdateResult +export type ReturningRow = O extends + | InsertResult + | DeleteResult + | UpdateResult + | MergeResult ? Selection : O & Selection -export type ReturningAllRow = O extends InsertResult - ? AllSelection - : O extends DeleteResult - ? AllSelection - : O extends UpdateResult +export type ReturningCallbackRow = O extends + | InsertResult + | DeleteResult + | UpdateResult + | MergeResult + ? CallbackSelection + : O & CallbackSelection + +export type ReturningAllRow = O extends + | InsertResult + | DeleteResult + | UpdateResult + | MergeResult ? AllSelection : O & AllSelection diff --git a/src/parser/select-parser.ts b/src/parser/select-parser.ts index f48a02d09..f39fbbc44 100644 --- a/src/parser/select-parser.ts +++ b/src/parser/select-parser.ts @@ -6,6 +6,7 @@ import { AnyAliasedColumnWithTable, AnyColumn, AnyColumnWithTable, + DrainOuterGeneric, ExtractColumnType, } from '../util/type-utils.js' import { parseAliasedStringReference } from './reference-parser.js' @@ -17,7 +18,7 @@ import { AliasedExpressionOrFactory, parseAliasedExpression, } from './expression-parser.js' -import { Selectable, SelectType } from '../util/column-type.js' +import { SelectType } from '../util/column-type.js' import { parseTable } from './table-parser.js' import { AliasedExpression } from '../expression/expression.js' import { @@ -33,132 +34,134 @@ export type SelectExpression = | DynamicReferenceBuilder | AliasedExpressionOrFactory +export type SelectCallback = ( + eb: ExpressionBuilder, +) => ReadonlyArray> + +/** + * Turns a SelectExpression or a union of them into a selection object. + */ +export type Selection< + DB, + TB extends keyof DB, + SE, + // Inline version of DrainOuterGeneric for performance reasons. + // Don't replace with DrainOuterGeneric! +> = [DB] extends [unknown] + ? { + [E in FlattenSelectExpression as ExtractAliasFromSelectExpression]: SelectType< + ExtractTypeFromSelectExpression + > + } + : {} + +/** + * Turns a SelectCallback into a selection object. + */ +export type CallbackSelection = CB extends ( + eb: any, +) => ReadonlyArray + ? Selection + : never + export type SelectArg< DB, TB extends keyof DB, - SE extends SelectExpression + SE extends SelectExpression, > = | SE | ReadonlyArray | ((eb: ExpressionBuilder) => ReadonlyArray) -export type Selection = { - [A in ExtractAliasFromSelectExpression]: SelectType< - ExtractTypeFromSelectExpression - > -} +type FlattenSelectExpression = SE extends DynamicReferenceBuilder + ? { [R in RA]: DynamicReferenceBuilder }[RA] + : SE type ExtractAliasFromSelectExpression = SE extends string ? ExtractAliasFromStringSelectExpression : SE extends AliasedExpression - ? EA - : SE extends (qb: any) => AliasedExpression - ? EA - : SE extends DynamicReferenceBuilder - ? ExtractAliasFromStringSelectExpression - : never + ? EA + : SE extends (qb: any) => AliasedExpression + ? EA + : SE extends DynamicReferenceBuilder + ? ExtractAliasFromStringSelectExpression + : never type ExtractAliasFromStringSelectExpression = SE extends `${string}.${string}.${string} as ${infer A}` ? A : SE extends `${string}.${string} as ${infer A}` - ? A - : SE extends `${string} as ${infer A}` - ? A - : SE extends `${string}.${string}.${infer C}` - ? C - : SE extends `${string}.${infer C}` - ? C - : SE + ? A + : SE extends `${string} as ${infer A}` + ? A + : SE extends `${string}.${string}.${infer C}` + ? C + : SE extends `${string}.${infer C}` + ? C + : SE type ExtractTypeFromSelectExpression< DB, TB extends keyof DB, SE, - A extends keyof any > = SE extends string - ? ExtractTypeFromStringSelectExpression - : SE extends AliasedSelectQueryBuilder - ? QA extends A - ? O[keyof O] | null - : never - : SE extends ( - qb: any - ) => AliasedSelectQueryBuilder - ? QA extends A + ? ExtractTypeFromStringSelectExpression + : SE extends AliasedSelectQueryBuilder ? O[keyof O] | null - : never - : SE extends AliasedExpression - ? EA extends A - ? O - : never - : SE extends (qb: any) => AliasedExpression - ? EA extends A - ? O - : never - : SE extends DynamicReferenceBuilder - ? A extends ExtractAliasFromStringSelectExpression - ? ExtractTypeFromStringSelectExpression | undefined - : never - : never + : SE extends (eb: any) => AliasedSelectQueryBuilder + ? O[keyof O] | null + : SE extends AliasedExpression + ? O + : SE extends (eb: any) => AliasedExpression + ? O + : SE extends DynamicReferenceBuilder + ? ExtractTypeFromStringSelectExpression | undefined + : never type ExtractTypeFromStringSelectExpression< DB, TB extends keyof DB, SE extends string, - A extends keyof any -> = SE extends `${infer SC}.${infer T}.${infer C} as ${infer RA}` - ? RA extends A - ? `${SC}.${T}` extends TB - ? C extends keyof DB[`${SC}.${T}`] - ? DB[`${SC}.${T}`][C] - : never +> = SE extends `${infer SC}.${infer T}.${infer C} as ${string}` + ? `${SC}.${T}` extends TB + ? C extends keyof DB[`${SC}.${T}`] + ? DB[`${SC}.${T}`][C] : never : never - : SE extends `${infer T}.${infer C} as ${infer RA}` - ? RA extends A + : SE extends `${infer T}.${infer C} as ${string}` ? T extends TB ? C extends keyof DB[T] ? DB[T][C] : never : never - : never - : SE extends `${infer C} as ${infer RA}` - ? RA extends A - ? C extends AnyColumn - ? ExtractColumnType - : never - : never - : SE extends `${infer SC}.${infer T}.${infer C}` - ? C extends A - ? `${SC}.${T}` extends TB - ? C extends keyof DB[`${SC}.${T}`] - ? DB[`${SC}.${T}`][C] - : never - : never - : never - : SE extends `${infer T}.${infer C}` - ? C extends A - ? T extends TB - ? C extends keyof DB[T] - ? DB[T][C] + : SE extends `${infer C} as ${string}` + ? C extends AnyColumn + ? ExtractColumnType : never - : never - : never - : SE extends A - ? SE extends AnyColumn - ? ExtractColumnType - : never - : never + : SE extends `${infer SC}.${infer T}.${infer C}` + ? `${SC}.${T}` extends TB + ? C extends keyof DB[`${SC}.${T}`] + ? DB[`${SC}.${T}`][C] + : never + : never + : SE extends `${infer T}.${infer C}` + ? T extends TB + ? C extends keyof DB[T] + ? DB[T][C] + : never + : never + : SE extends AnyColumn + ? ExtractColumnType + : never -export type AllSelection = Selectable<{ +export type AllSelection = DrainOuterGeneric<{ [C in AnyColumn]: { - [T in TB]: C extends keyof DB[T] ? DB[T][C] : never + [T in TB]: SelectType }[TB] }> export function parseSelectArg( - selection: SelectArg> + selection: SelectArg>, ): SelectionNode[] { if (isFunction(selection)) { return parseSelectArg(selection(expressionBuilder())) @@ -170,7 +173,7 @@ export function parseSelectArg( } function parseSelectExpression( - selection: SelectExpression + selection: SelectExpression, ): SelectionNode { if (isString(selection)) { return SelectionNode.create(parseAliasedStringReference(selection)) @@ -197,6 +200,6 @@ function parseSelectAllArg(table: string): SelectionNode { } throw new Error( - `invalid value selectAll expression: ${JSON.stringify(table)}` + `invalid value selectAll expression: ${JSON.stringify(table)}`, ) } diff --git a/src/parser/set-operation-parser.ts b/src/parser/set-operation-parser.ts index cf06e56ed..e35bcbadf 100644 --- a/src/parser/set-operation-parser.ts +++ b/src/parser/set-operation-parser.ts @@ -1,13 +1,36 @@ +import { + ExpressionBuilder, + createExpressionBuilder, +} from '../expression/expression-builder.js' import { Expression } from '../expression/expression.js' import { SetOperator, SetOperationNode, } from '../operation-node/set-operation-node.js' +import { isFunction, isReadonlyArray } from '../util/object-utils.js' +import { parseExpression } from './expression-parser.js' + +export type SetOperandExpression = + | Expression + | ReadonlyArray> + | (( + eb: ExpressionBuilder, + ) => Expression | ReadonlyArray>) -export function parseSetOperation( +export function parseSetOperations( operator: SetOperator, - expression: Expression, - all: boolean + expression: SetOperandExpression, + all: boolean, ) { - return SetOperationNode.create(operator, expression.toOperationNode(), all) + if (isFunction(expression)) { + expression = expression(createExpressionBuilder()) + } + + if (!isReadonlyArray(expression)) { + expression = [expression] + } + + return expression.map((expr) => + SetOperationNode.create(operator, parseExpression(expr), all), + ) } diff --git a/src/parser/table-parser.ts b/src/parser/table-parser.ts index 4c641b02b..9c665c16e 100644 --- a/src/parser/table-parser.ts +++ b/src/parser/table-parser.ts @@ -20,10 +20,11 @@ export type TableExpressionOrList = | ReadonlyArray> export type TableReference = - | AnyAliasedTable - | AnyTable + | SimpleTableReference | AliasedExpression +export type SimpleTableReference = AnyAliasedTable | AnyTable + export type AnyAliasedTable = `${AnyTable} as ${string}` export type TableReferenceOrList = @@ -39,8 +40,8 @@ export type From = DrainOuterGeneric<{ >]: C extends ExtractAliasFromTableExpression ? ExtractRowTypeFromTableExpression : C extends keyof DB - ? DB[C] - : never + ? DB[C] + : never }> export type FromTables = DrainOuterGeneric< @@ -48,14 +49,16 @@ export type FromTables = DrainOuterGeneric< > export type ExtractTableAlias = TE extends `${string} as ${infer TA}` - ? TA + ? TA extends keyof DB + ? TA + : never : TE extends keyof DB - ? TE - : never + ? TE + : never export type PickTableWithAlias< DB, - T extends AnyAliasedTable + T extends AnyAliasedTable, > = T extends `${infer TB} as ${infer A}` ? TB extends keyof DB ? ShallowRecord @@ -63,17 +66,21 @@ export type PickTableWithAlias< : never type ExtractAliasFromTableExpression = TE extends string - ? ExtractTableAlias + ? TE extends `${string} as ${infer TA}` + ? TA + : TE extends keyof DB + ? TE + : never : TE extends AliasedExpression - ? QA - : TE extends (qb: any) => AliasedExpression - ? QA - : never + ? QA + : TE extends (qb: any) => AliasedExpression + ? QA + : never type ExtractRowTypeFromTableExpression< DB, TE, - A extends keyof any + A extends keyof any, > = TE extends `${infer T} as ${infer TA}` ? TA extends A ? T extends keyof DB @@ -81,23 +88,23 @@ type ExtractRowTypeFromTableExpression< : never : never : TE extends A - ? TE extends keyof DB - ? DB[TE] - : never - : TE extends AliasedExpression - ? QA extends A - ? O - : never - : TE extends (qb: any) => AliasedExpression - ? QA extends A - ? O - : never - : never + ? TE extends keyof DB + ? DB[TE] + : never + : TE extends AliasedExpression + ? QA extends A + ? O + : never + : TE extends (qb: any) => AliasedExpression + ? QA extends A + ? O + : never + : never type AnyTable = keyof DB & string export function parseTableExpressionOrList( - table: TableExpressionOrList + table: TableExpressionOrList, ): OperationNode[] { if (isReadonlyArray(table)) { return table.map((it) => parseTableExpression(it)) @@ -107,7 +114,7 @@ export function parseTableExpressionOrList( } export function parseTableExpression( - table: TableExpression + table: TableExpression, ): OperationNode { if (isString(table)) { return parseAliasedTable(table) diff --git a/src/parser/top-parser.ts b/src/parser/top-parser.ts new file mode 100644 index 000000000..6a2fce445 --- /dev/null +++ b/src/parser/top-parser.ts @@ -0,0 +1,25 @@ +import { TopModifier, TopNode } from '../operation-node/top-node.js' +import { isBigInt, isNumber, isUndefined } from '../util/object-utils.js' + +export function parseTop( + expression: number | bigint, + modifiers?: TopModifier, +): TopNode { + if (!isNumber(expression) && !isBigInt(expression)) { + throw new Error(`Invalid top expression: ${expression}`) + } + + if (!isUndefined(modifiers) && !isTopModifiers(modifiers)) { + throw new Error(`Invalid top modifiers: ${modifiers}`) + } + + return TopNode.create(expression, modifiers) +} + +function isTopModifiers(modifiers: string): modifiers is TopModifier { + return ( + modifiers === 'percent' || + modifiers === 'with ties' || + modifiers === 'percent with ties' + ) +} diff --git a/src/parser/tuple-parser.ts b/src/parser/tuple-parser.ts new file mode 100644 index 000000000..56ecb7ce3 --- /dev/null +++ b/src/parser/tuple-parser.ts @@ -0,0 +1,83 @@ +import { DrainOuterGeneric } from '../util/type-utils.js' +import { ExtractTypeFromReferenceExpression } from './reference-parser.js' +import { ExtractTypeFromValueExpression } from './value-parser.js' + +export type RefTuple2 = DrainOuterGeneric< + [ + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ] +> + +export type RefTuple3 = DrainOuterGeneric< + [ + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ] +> + +export type RefTuple4< + DB, + TB extends keyof DB, + R1, + R2, + R3, + R4, +> = DrainOuterGeneric< + [ + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ] +> + +export type RefTuple5< + DB, + TB extends keyof DB, + R1, + R2, + R3, + R4, + R5, +> = DrainOuterGeneric< + [ + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ExtractTypeFromReferenceExpression, + ] +> + +export type ValTuple2 = DrainOuterGeneric< + [ExtractTypeFromValueExpression, ExtractTypeFromValueExpression] +> + +export type ValTuple3 = DrainOuterGeneric< + [ + ExtractTypeFromValueExpression, + ExtractTypeFromValueExpression, + ExtractTypeFromValueExpression, + ] +> + +export type ValTuple4 = DrainOuterGeneric< + [ + ExtractTypeFromValueExpression, + ExtractTypeFromValueExpression, + ExtractTypeFromValueExpression, + ExtractTypeFromValueExpression, + ] +> + +export type ValTuple5 = DrainOuterGeneric< + [ + ExtractTypeFromValueExpression, + ExtractTypeFromValueExpression, + ExtractTypeFromValueExpression, + ExtractTypeFromValueExpression, + ExtractTypeFromValueExpression, + ] +> diff --git a/src/parser/unary-operation-parser.ts b/src/parser/unary-operation-parser.ts index 24549d3ec..dce20f353 100644 --- a/src/parser/unary-operation-parser.ts +++ b/src/parser/unary-operation-parser.ts @@ -13,23 +13,23 @@ export type ExistsExpression = ExpressionOrFactory< > export function parseExists( - operand: ExistsExpression + operand: ExistsExpression, ): UnaryOperationNode { return parseUnaryOperation('exists', operand) } export function parseNotExists( - operand: ExistsExpression + operand: ExistsExpression, ): UnaryOperationNode { return parseUnaryOperation('not exists', operand) } export function parseUnaryOperation( operator: UnaryOperator, - operand: ReferenceExpression + operand: ReferenceExpression, ): UnaryOperationNode { return UnaryOperationNode.create( OperatorNode.create(operator), - parseReferenceExpression(operand) + parseReferenceExpression(operand), ) } diff --git a/src/parser/update-set-parser.ts b/src/parser/update-set-parser.ts index 3a03dfa13..c3ce3fe4c 100644 --- a/src/parser/update-set-parser.ts +++ b/src/parser/update-set-parser.ts @@ -1,9 +1,17 @@ import { ColumnNode } from '../operation-node/column-node.js' import { ColumnUpdateNode } from '../operation-node/column-update-node.js' -import { expressionBuilder, ExpressionBuilder } from '../expression/expression-builder.js' +import { + expressionBuilder, + ExpressionBuilder, +} from '../expression/expression-builder.js' import { UpdateKeys, UpdateType } from '../util/column-type.js' import { isFunction } from '../util/object-utils.js' import { parseValueExpression, ValueExpression } from './value-parser.js' +import { + ExtractRawTypeFromReferenceExpression, + parseReferenceExpression, + ReferenceExpression, +} from './reference-parser.js' export type UpdateObject = { [C in UpdateKeys]?: @@ -14,28 +22,50 @@ export type UpdateObject = { export type UpdateObjectFactory< DB, TB extends keyof DB, - UT extends keyof DB + UT extends keyof DB, > = (eb: ExpressionBuilder) => UpdateObject -export type UpdateExpression< +export type UpdateObjectExpression< DB, TB extends keyof DB, - UT extends keyof DB = TB + UT extends keyof DB = TB, > = UpdateObject | UpdateObjectFactory -export function parseUpdateExpression( - update: UpdateExpression +export type ExtractUpdateTypeFromReferenceExpression< + DB, + TB extends keyof DB, + RE, + DV = unknown, +> = UpdateType> + +export function parseUpdate( + ...args: + | [UpdateObjectExpression] + | [ReferenceExpression, ValueExpression] +): ReadonlyArray { + if (args.length === 2) { + return [ + ColumnUpdateNode.create( + parseReferenceExpression(args[0]), + parseValueExpression(args[1]), + ), + ] + } + + return parseUpdateObjectExpression(args[0]) +} + +export function parseUpdateObjectExpression( + update: UpdateObjectExpression, ): ReadonlyArray { - const updateObj = isFunction(update) - ? update(expressionBuilder()) - : update + const updateObj = isFunction(update) ? update(expressionBuilder()) : update return Object.entries(updateObj) .filter(([_, value]) => value !== undefined) .map(([key, value]) => { return ColumnUpdateNode.create( ColumnNode.create(key), - parseValueExpression(value) + parseValueExpression(value), ) }) } diff --git a/src/parser/value-parser.ts b/src/parser/value-parser.ts index d5d887df1..51bacd43c 100644 --- a/src/parser/value-parser.ts +++ b/src/parser/value-parser.ts @@ -1,7 +1,12 @@ import { PrimitiveValueListNode } from '../operation-node/primitive-value-list-node.js' import { ValueListNode } from '../operation-node/value-list-node.js' import { ValueNode } from '../operation-node/value-node.js' -import { isReadonlyArray } from '../util/object-utils.js' +import { + isBoolean, + isNull, + isNumber, + isReadonlyArray, +} from '../util/object-utils.js' import { parseExpression, ExpressionOrFactory, @@ -9,7 +14,7 @@ import { } from './expression-parser.js' import { OperationNode } from '../operation-node/operation-node.js' import { Expression } from '../expression/expression.js' -import { SelectQueryBuilder } from '../query-builder/select-query-builder.js' +import { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js' export type ValueExpression = | V @@ -25,18 +30,15 @@ export type ExtractTypeFromValueExpressionOrList = VE extends ReadonlyArray< ? ExtractTypeFromValueExpression : ExtractTypeFromValueExpression -type ExtractTypeFromValueExpression = VE extends SelectQueryBuilder< - any, - any, - Record -> - ? SV - : VE extends Expression - ? V - : VE +export type ExtractTypeFromValueExpression = + VE extends SelectQueryBuilderExpression> + ? SV + : VE extends Expression + ? V + : VE export function parseValueExpressionOrList( - arg: ValueExpressionOrList + arg: ValueExpressionOrList, ): OperationNode { if (isReadonlyArray(arg)) { return parseValueExpressionList(arg) @@ -46,7 +48,7 @@ export function parseValueExpressionOrList( } export function parseValueExpression( - exp: ValueExpression + exp: ValueExpression, ): OperationNode { if (isExpressionOrFactory(exp)) { return parseExpression(exp) @@ -55,8 +57,24 @@ export function parseValueExpression( return ValueNode.create(exp) } +export function isSafeImmediateValue( + value: unknown, +): value is number | boolean | null { + return isNumber(value) || isBoolean(value) || isNull(value) +} + +export function parseSafeImmediateValue( + value: number | boolean | null, +): ValueNode { + if (!isSafeImmediateValue(value)) { + throw new Error(`unsafe immediate value ${JSON.stringify(value)}`) + } + + return ValueNode.createImmediate(value) +} + function parseValueExpressionList( - arg: ReadonlyArray> + arg: ReadonlyArray>, ): PrimitiveValueListNode | ValueListNode { if (arg.some(isExpressionOrFactory)) { return ValueListNode.create(arg.map((it) => parseValueExpression(it))) diff --git a/src/parser/with-parser.ts b/src/parser/with-parser.ts index 313632b7f..b9c05e661 100644 --- a/src/parser/with-parser.ts +++ b/src/parser/with-parser.ts @@ -1,15 +1,18 @@ import { UpdateQueryBuilder } from '../query-builder/update-query-builder.js' import { DeleteQueryBuilder } from '../query-builder/delete-query-builder.js' import { InsertQueryBuilder } from '../query-builder/insert-query-builder.js' -import { CommonTableExpressionNode } from '../operation-node/common-table-expression-node.js' import { CommonTableExpressionNameNode } from '../operation-node/common-table-expression-name-node.js' import { QueryCreator } from '../query-creator.js' -import { createQueryCreator } from './parse-utils.js' import { Expression } from '../expression/expression.js' import { ShallowRecord } from '../util/type-utils.js' +import { OperationNode } from '../operation-node/operation-node.js' +import { createQueryCreator } from './parse-utils.js' +import { isFunction } from '../util/object-utils.js' +import { CTEBuilder, CTEBuilderCallback } from '../query-builder/cte-builder.js' +import { CommonTableExpressionNode } from '../operation-node/common-table-expression-node.js' export type CommonTableExpression = ( - creator: QueryCreator + creator: QueryCreator, ) => CommonTableExpressionOutput export type RecursiveCommonTableExpression = ( @@ -18,13 +21,13 @@ export type RecursiveCommonTableExpression = ( // Recursive CTE can select from itself. [K in ExtractTableFromCommonTableExpressionName]: ExtractRowFromCommonTableExpressionName } - > + >, ) => CommonTableExpressionOutput export type QueryCreatorWithCommonTableExpression< DB, CN extends string, - CTE + CTE, > = QueryCreator< DB & { [K in ExtractTableFromCommonTableExpressionName]: ExtractRowFromCommonTableExpression @@ -49,17 +52,17 @@ type CommonTableExpressionOutput = * would result in `Pick`. */ type ExtractRowFromCommonTableExpression = CTE extends ( - creator: QueryCreator + creator: QueryCreator, ) => infer Q ? Q extends Expression ? QO : Q extends InsertQueryBuilder - ? QO - : Q extends UpdateQueryBuilder - ? QO - : Q extends DeleteQueryBuilder - ? QO - : never + ? QO + : Q extends UpdateQueryBuilder + ? QO + : Q extends DeleteQueryBuilder + ? QO + : never : never /** @@ -91,23 +94,39 @@ type ExtractColumnNamesFromColumnList = : R export function parseCommonTableExpression( - name: string, - expression: CommonTableExpression + nameOrBuilderCallback: string | CTEBuilderCallback, + expression: CommonTableExpression, ): CommonTableExpressionNode { - const builder = expression(createQueryCreator()) + const expressionNode = expression(createQueryCreator()).toOperationNode() + + if (isFunction(nameOrBuilderCallback)) { + return nameOrBuilderCallback( + cteBuilderFactory(expressionNode), + ).toOperationNode() + } return CommonTableExpressionNode.create( - parseCommonTableExpressionName(name), - builder.toOperationNode() + parseCommonTableExpressionName(nameOrBuilderCallback), + expressionNode, ) } +function cteBuilderFactory(expressionNode: OperationNode) { + return (name: string) => { + return new CTEBuilder({ + node: CommonTableExpressionNode.create( + parseCommonTableExpressionName(name), + expressionNode, + ), + }) + } +} + function parseCommonTableExpressionName( - name: string + name: string, ): CommonTableExpressionNameNode { if (name.includes('(')) { const parts = name.split(/[\(\)]/) - const table = parts[0] const columns = parts[1].split(',').map((it) => it.trim()) diff --git a/src/plugin/camel-case/camel-case-plugin.ts b/src/plugin/camel-case/camel-case-plugin.ts index 8be7aaae7..1ff1bfaa5 100644 --- a/src/plugin/camel-case/camel-case-plugin.ts +++ b/src/plugin/camel-case/camel-case-plugin.ts @@ -1,11 +1,6 @@ import { QueryResult } from '../../driver/database-connection.js' import { RootOperationNode } from '../../query-compiler/query-compiler.js' -import { - isArrayBufferOrView, - isBuffer, - isDate, - isObject, -} from '../../util/object-utils.js' +import { isPlainObject } from '../../util/object-utils.js' import { UnknownRow } from '../../util/type-utils.js' import { KyselyPlugin, @@ -96,9 +91,9 @@ export interface CamelCasePluginOptions { * ``` * * As you can see from the example, __everything__ needs to be defined - * in camelCase in the typescript code: the table names, the columns, - * schemas, __everything__. When using the `CamelCasePlugin` Kysely - * works as if the database was defined in camelCase. + * in camelCase in the typescript code: table names, columns, schemas, + * __everything__. When using the `CamelCasePlugin` Kysely works as if + * the database was defined in camelCase. * * There are various options you can give to the plugin to modify * the way identifiers are converted. See {@link CamelCasePluginOptions}. @@ -128,7 +123,7 @@ export class CamelCasePlugin implements KyselyPlugin { this.#snakeCase = createSnakeCaseMapper(opt) this.#snakeCaseTransformer = new SnakeCaseTransformer( - this.snakeCase.bind(this) + this.snakeCase.bind(this), ) } @@ -137,7 +132,7 @@ export class CamelCasePlugin implements KyselyPlugin { } async transformResult( - args: PluginTransformResultArgs + args: PluginTransformResultArgs, ): Promise> { if (args.result.rows && Array.isArray(args.result.rows)) { return { @@ -175,13 +170,7 @@ export class CamelCasePlugin implements KyselyPlugin { function canMap( obj: unknown, - opt: CamelCasePluginOptions + opt: CamelCasePluginOptions, ): obj is Record { - return ( - isObject(obj) && - !isDate(obj) && - !isBuffer(obj) && - !isArrayBufferOrView(obj) && - !opt?.maintainNestedObjectKeys - ) + return isPlainObject(obj) && !opt?.maintainNestedObjectKeys } diff --git a/src/plugin/deduplicate-joins/deduplicate-joins-plugin.ts b/src/plugin/deduplicate-joins/deduplicate-joins-plugin.ts index b5d95864c..a95896c40 100644 --- a/src/plugin/deduplicate-joins/deduplicate-joins-plugin.ts +++ b/src/plugin/deduplicate-joins/deduplicate-joins-plugin.ts @@ -21,7 +21,7 @@ export class DeduplicateJoinsPlugin implements KyselyPlugin { } transformResult( - args: PluginTransformResultArgs + args: PluginTransformResultArgs, ): Promise> { return Promise.resolve(args.result) } diff --git a/src/plugin/deduplicate-joins/deduplicate-joins-transformer.ts b/src/plugin/deduplicate-joins/deduplicate-joins-transformer.ts index 9be6b922d..e7c92e534 100644 --- a/src/plugin/deduplicate-joins/deduplicate-joins-transformer.ts +++ b/src/plugin/deduplicate-joins/deduplicate-joins-transformer.ts @@ -19,7 +19,7 @@ export class DeduplicateJoinsTransformer extends OperationNodeTransformer { } #transformQuery< - T extends SelectQueryNode | UpdateQueryNode | DeleteQueryNode + T extends SelectQueryNode | UpdateQueryNode | DeleteQueryNode, >(node: T): T { if (!node.joins || node.joins.length === 0) { return node diff --git a/src/plugin/immediate-value/immediate-value-plugin.ts b/src/plugin/immediate-value/immediate-value-plugin.ts index d97e725a4..ee6c1b13b 100644 --- a/src/plugin/immediate-value/immediate-value-plugin.ts +++ b/src/plugin/immediate-value/immediate-value-plugin.ts @@ -24,7 +24,7 @@ export class ImmediateValuePlugin implements KyselyPlugin { } transformResult( - args: PluginTransformResultArgs + args: PluginTransformResultArgs, ): Promise> { return Promise.resolve(args.result) } diff --git a/src/plugin/kysely-plugin.ts b/src/plugin/kysely-plugin.ts index a2dd5184f..208bbcc8a 100644 --- a/src/plugin/kysely-plugin.ts +++ b/src/plugin/kysely-plugin.ts @@ -41,7 +41,7 @@ export interface KyselyPlugin { * You can modify the result and return the modifier result. */ transformResult( - args: PluginTransformResultArgs + args: PluginTransformResultArgs, ): Promise> } diff --git a/src/plugin/noop-plugin.ts b/src/plugin/noop-plugin.ts index 89b75ea1f..756d2a7c2 100644 --- a/src/plugin/noop-plugin.ts +++ b/src/plugin/noop-plugin.ts @@ -13,7 +13,7 @@ export class NoopPlugin implements KyselyPlugin { } async transformResult( - args: PluginTransformResultArgs + args: PluginTransformResultArgs, ): Promise> { return args.result } diff --git a/src/plugin/parse-json-results/parse-json-results-plugin.ts b/src/plugin/parse-json-results/parse-json-results-plugin.ts new file mode 100644 index 000000000..59c612d29 --- /dev/null +++ b/src/plugin/parse-json-results/parse-json-results-plugin.ts @@ -0,0 +1,115 @@ +import { QueryResult } from '../../driver/database-connection.js' +import { RootOperationNode } from '../../query-compiler/query-compiler.js' +import { isPlainObject, isString } from '../../util/object-utils.js' +import { UnknownRow } from '../../util/type-utils.js' +import { + KyselyPlugin, + PluginTransformQueryArgs, + PluginTransformResultArgs, +} from '../kysely-plugin.js' + +export interface ParseJSONResultsPluginOptions { + /** + * When `'in-place'`, arrays' and objects' values are parsed in-place. This is + * the most time and space efficient option. + * + * This can result in runtime errors if some objects/arrays are readonly. + * + * When `'create'`, new arrays and objects are created to avoid such errors. + * + * Defaults to `'in-place'`. + */ + objectStrategy?: ObjectStrategy +} + +type ObjectStrategy = 'in-place' | 'create' + +/** + * Parses JSON strings in query results into JSON objects. + * + * This plugin can be useful with dialects that don't automatically parse + * JSON into objects and arrays but return JSON strings instead. + * + * ```ts + * const db = new Kysely({ + * ... + * plugins: [new ParseJSONResultsPlugin()] + * }) + * ``` + */ +export class ParseJSONResultsPlugin implements KyselyPlugin { + readonly #objectStrategy: ObjectStrategy + + constructor(readonly opt: ParseJSONResultsPluginOptions = {}) { + this.#objectStrategy = opt.objectStrategy || 'in-place' + } + + // noop + transformQuery(args: PluginTransformQueryArgs): RootOperationNode { + return args.node + } + + async transformResult( + args: PluginTransformResultArgs, + ): Promise> { + return { + ...args.result, + rows: parseArray(args.result.rows, this.#objectStrategy), + } + } +} + +function parseArray(arr: T[], objectStrategy: ObjectStrategy): T[] { + const target = objectStrategy === 'create' ? new Array(arr.length) : arr + + for (let i = 0; i < arr.length; ++i) { + target[i] = parse(arr[i], objectStrategy) as T + } + + return target +} + +function parse(obj: unknown, objectStrategy: ObjectStrategy): unknown { + if (isString(obj)) { + return parseString(obj) + } + + if (Array.isArray(obj)) { + return parseArray(obj, objectStrategy) + } + + if (isPlainObject(obj)) { + return parseObject(obj, objectStrategy) + } + + return obj +} + +function parseString(str: string): unknown { + if (maybeJson(str)) { + try { + return parse(JSON.parse(str), 'in-place') + } catch (err) { + // this catch block is intentionally empty. + } + } + + return str +} + +function maybeJson(value: string): boolean { + return value.match(/^[\[\{]/) != null +} + +function parseObject( + obj: Record, + objectStrategy: ObjectStrategy, +): Record { + const target = objectStrategy === 'create' ? {} : obj + + for (const key in obj) { + target[key] = parse(obj[key], objectStrategy) + } + + return target +} diff --git a/src/plugin/with-schema/with-schema-plugin.ts b/src/plugin/with-schema/with-schema-plugin.ts index c0c9aae4b..44ec832de 100644 --- a/src/plugin/with-schema/with-schema-plugin.ts +++ b/src/plugin/with-schema/with-schema-plugin.ts @@ -20,7 +20,7 @@ export class WithSchemaPlugin implements KyselyPlugin { } async transformResult( - args: PluginTransformResultArgs + args: PluginTransformResultArgs, ): Promise> { return args.result } diff --git a/src/plugin/with-schema/with-schema-transformer.ts b/src/plugin/with-schema/with-schema-transformer.ts index b9e74ca3e..af14b0b3d 100644 --- a/src/plugin/with-schema/with-schema-transformer.ts +++ b/src/plugin/with-schema/with-schema-transformer.ts @@ -31,11 +31,13 @@ const ROOT_OPERATION_NODES: Record = freeze({ RawNode: true, SelectQueryNode: true, UpdateQueryNode: true, + MergeQueryNode: true, }) export class WithSchemaTransformer extends OperationNodeTransformer { readonly #schema: string readonly #schemableIds = new Set() + readonly #ctes = new Set() constructor(schema: string) { super() @@ -47,6 +49,12 @@ export class WithSchemaTransformer extends OperationNodeTransformer { return super.transformNodeImpl(node) } + const ctes = this.#collectCTEs(node) + + for (const cte of ctes) { + this.#ctes.add(cte) + } + const tables = this.#collectSchemableIds(node) for (const table of tables) { @@ -59,11 +67,15 @@ export class WithSchemaTransformer extends OperationNodeTransformer { this.#schemableIds.delete(table) } + for (const cte of ctes) { + this.#ctes.delete(cte) + } + return transformed } protected override transformSchemableIdentifier( - node: SchemableIdentifierNode + node: SchemableIdentifierNode, ): SchemableIdentifierNode { const transformed = super.transformSchemableIdentifier(node) @@ -88,7 +100,7 @@ export class WithSchemaTransformer extends OperationNodeTransformer { ...transformed, table: TableNode.createWithSchema( this.#schema, - transformed.table.table.identifier.name + transformed.table.table.identifier.name, ), } } @@ -124,22 +136,32 @@ export class WithSchemaTransformer extends OperationNodeTransformer { } } - if ('with' in node && node.with) { - this.#removeCommonTableExpressionTables(node.with, schemableIds) + if ('using' in node && node.using) { + this.#collectSchemableIdsFromTableExpr(node.using, schemableIds) } return schemableIds } + #collectCTEs(node: RootOperationNode): Set { + const ctes = new Set() + + if ('with' in node && node.with) { + this.#collectCTEIds(node.with, ctes) + } + + return ctes + } + #collectSchemableIdsFromTableExpr( node: OperationNode, - schemableIds: Set + schemableIds: Set, ): void { const table = TableNode.is(node) ? node : AliasNode.is(node) && TableNode.is(node.node) - ? node.node - : null + ? node.node + : null if (table) { this.#collectSchemableId(table.table, schemableIds) @@ -148,19 +170,22 @@ export class WithSchemaTransformer extends OperationNodeTransformer { #collectSchemableId( node: SchemableIdentifierNode, - schemableIds: Set + schemableIds: Set, ): void { - if (!this.#schemableIds.has(node.identifier.name)) { - schemableIds.add(node.identifier.name) + const id = node.identifier.name + + if (!this.#schemableIds.has(id) && !this.#ctes.has(id)) { + schemableIds.add(id) } } - #removeCommonTableExpressionTables( - node: WithNode, - schemableIds: Set - ) { + #collectCTEIds(node: WithNode, ctes: Set): void { for (const expr of node.expressions) { - schemableIds.delete(expr.name.table.table.identifier.name) + const cteId = expr.name.table.table.identifier.name + + if (!this.#ctes.has(cteId)) { + ctes.add(cteId) + } } } } diff --git a/src/query-builder/aggregate-function-builder.ts b/src/query-builder/aggregate-function-builder.ts index 51bb7aeb4..a852f5ae2 100644 --- a/src/query-builder/aggregate-function-builder.ts +++ b/src/query-builder/aggregate-function-builder.ts @@ -5,23 +5,23 @@ import { IdentifierNode } from '../operation-node/identifier-node.js' import { preventAwait } from '../util/prevent-await.js' import { OverBuilder } from './over-builder.js' import { createOverBuilder } from '../parser/parse-utils.js' -import { AliasedExpression, Expression } from '../expression/expression.js' +import { + AliasableExpression, + AliasedExpression, + Expression, +} from '../expression/expression.js' import { ReferenceExpression } from '../parser/reference-parser.js' import { ComparisonOperatorExpression, OperandValueExpressionOrList, - parseReferentialComparison, - parseWhere, + parseReferentialBinaryOperation, + parseValueBinaryOperationOrExpression, } from '../parser/binary-operation-parser.js' -import { - ExistsExpression, - parseExists, - parseNotExists, -} from '../parser/unary-operation-parser.js' -import { WhereExpressionFactory } from './where-interface.js' +import { SqlBool } from '../util/type-utils.js' +import { ExpressionOrFactory } from '../parser/expression-parser.js' export class AggregateFunctionBuilder - implements Expression + implements AliasableExpression { readonly #props: AggregateFunctionBuilderProps @@ -44,7 +44,7 @@ export class AggregateFunctionBuilder * const result = await db * .selectFrom('person') * .select( - * eb => eb.fn.count('id').as('person_count') + * (eb) => eb.fn.count('id').as('person_count') * ) * .executeTakeFirstOrThrow() * @@ -60,7 +60,7 @@ export class AggregateFunctionBuilder * ``` */ as( - alias: A + alias: A, ): AliasedAggregateFunctionBuilder { return new AliasedAggregateFunctionBuilder(this, alias) } @@ -90,7 +90,7 @@ export class AggregateFunctionBuilder return new AggregateFunctionBuilder({ ...this.#props, aggregateFunctionNode: AggregateFunctionNode.cloneWithDistinct( - this.#props.aggregateFunctionNode + this.#props.aggregateFunctionNode, ), }) } @@ -100,7 +100,7 @@ export class AggregateFunctionBuilder * * Similar to {@link WhereInterface}'s `where` method. * - * Also see {@link orFilterWhere}, {@link filterWhereExists} and {@link filterWhereRef}. + * Also see {@link filterWhereRef}. * * ### Examples * @@ -136,54 +136,25 @@ export class AggregateFunctionBuilder * from "person" * ``` */ - filterWhere>( + filterWhere< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( lhs: RE, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: VE, ): AggregateFunctionBuilder - filterWhere( - factory: WhereExpressionFactory + filterWhere>( + expression: E, ): AggregateFunctionBuilder - filterWhere(expression: Expression): AggregateFunctionBuilder - filterWhere(...args: any[]): any { return new AggregateFunctionBuilder({ ...this.#props, aggregateFunctionNode: AggregateFunctionNode.cloneWithFilter( this.#props.aggregateFunctionNode, - parseWhere(args) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - filterWhereExists( - arg: ExistsExpression - ): AggregateFunctionBuilder { - return new AggregateFunctionBuilder({ - ...this.#props, - aggregateFunctionNode: AggregateFunctionNode.cloneWithFilter( - this.#props.aggregateFunctionNode, - parseExists(arg) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - filterWhereNotExists( - arg: ExistsExpression - ): AggregateFunctionBuilder { - return new AggregateFunctionBuilder({ - ...this.#props, - aggregateFunctionNode: AggregateFunctionNode.cloneWithFilter( - this.#props.aggregateFunctionNode, - parseNotExists(arg) + parseValueBinaryOperationOrExpression(args), ), }) } @@ -220,99 +191,19 @@ export class AggregateFunctionBuilder * from "person" * ``` */ - filterWhereRef( - lhs: ReferenceExpression, + filterWhereRef< + LRE extends ReferenceExpression, + RRE extends ReferenceExpression, + >( + lhs: LRE, op: ComparisonOperatorExpression, - rhs: ReferenceExpression + rhs: RRE, ): AggregateFunctionBuilder { return new AggregateFunctionBuilder({ ...this.#props, aggregateFunctionNode: AggregateFunctionNode.cloneWithFilter( this.#props.aggregateFunctionNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orFilterWhere>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): AggregateFunctionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orFilterWhere( - factory: WhereExpressionFactory - ): AggregateFunctionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orFilterWhere( - expression: Expression - ): AggregateFunctionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orFilterWhere(...args: any[]): any { - return new AggregateFunctionBuilder({ - ...this.#props, - aggregateFunctionNode: AggregateFunctionNode.cloneWithOrFilter( - this.#props.aggregateFunctionNode, - parseWhere(args) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orFilterWhereExists( - arg: ExistsExpression - ): AggregateFunctionBuilder { - return new AggregateFunctionBuilder({ - ...this.#props, - aggregateFunctionNode: AggregateFunctionNode.cloneWithOrFilter( - this.#props.aggregateFunctionNode, - parseExists(arg) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orFilterWhereNotExists( - arg: ExistsExpression - ): AggregateFunctionBuilder { - return new AggregateFunctionBuilder({ - ...this.#props, - aggregateFunctionNode: AggregateFunctionNode.cloneWithOrFilter( - this.#props.aggregateFunctionNode, - parseNotExists(arg) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orFilterWhereRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): AggregateFunctionBuilder { - return new AggregateFunctionBuilder({ - ...this.#props, - aggregateFunctionNode: AggregateFunctionNode.cloneWithOrFilter( - this.#props.aggregateFunctionNode, - parseReferentialComparison(lhs, op, rhs) + parseReferentialBinaryOperation(lhs, op, rhs), ), }) } @@ -326,7 +217,7 @@ export class AggregateFunctionBuilder * const result = await db * .selectFrom('person') * .select( - * eb => eb.fn.avg('age').over().as('average_age') + * (eb) => eb.fn.avg('age').over().as('average_age') * ) * .execute() * ``` @@ -345,7 +236,7 @@ export class AggregateFunctionBuilder * const result = await db * .selectFrom('person') * .select( - * eb => eb.fn.avg('age').over( + * (eb) => eb.fn.avg('age').over( * ob => ob.partitionBy('last_name').orderBy('first_name', 'asc') * ).as('average_age') * ) @@ -360,7 +251,7 @@ export class AggregateFunctionBuilder * ``` */ over( - over?: OverBuilderCallback + over?: OverBuilderCallback, ): AggregateFunctionBuilder { const builder = createOverBuilder() @@ -368,7 +259,7 @@ export class AggregateFunctionBuilder ...this.#props, aggregateFunctionNode: AggregateFunctionNode.cloneWithOver( this.#props.aggregateFunctionNode, - (over ? over(builder) : builder).toOperationNode() + (over ? over(builder) : builder).toOperationNode(), ), }) } @@ -381,6 +272,29 @@ export class AggregateFunctionBuilder 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(): AggregateFunctionBuilder { + 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(): AggregateFunctionBuilder> { + return new AggregateFunctionBuilder(this.#props) + } + toOperationNode(): AggregateFunctionNode { return this.#props.aggregateFunctionNode } @@ -388,7 +302,7 @@ export class AggregateFunctionBuilder preventAwait( AggregateFunctionBuilder, - "don't await AggregateFunctionBuilder instances. They are never executed directly and are always just a part of a query." + "don't await AggregateFunctionBuilder instances. They are never executed directly and are always just a part of a query.", ) /** @@ -398,7 +312,7 @@ export class AliasedAggregateFunctionBuilder< DB, TB extends keyof DB, O = unknown, - A extends string = never + A extends string = never, > implements AliasedExpression { readonly #aggregateFunctionBuilder: AggregateFunctionBuilder @@ -406,7 +320,7 @@ export class AliasedAggregateFunctionBuilder< constructor( aggregateFunctionBuilder: AggregateFunctionBuilder, - alias: A + alias: A, ) { this.#aggregateFunctionBuilder = aggregateFunctionBuilder this.#alias = alias @@ -425,7 +339,7 @@ export class AliasedAggregateFunctionBuilder< toOperationNode(): AliasNode { return AliasNode.create( this.#aggregateFunctionBuilder.toOperationNode(), - IdentifierNode.create(this.#alias) + IdentifierNode.create(this.#alias), ) } } @@ -435,5 +349,5 @@ export interface AggregateFunctionBuilderProps { } export type OverBuilderCallback = ( - builder: OverBuilder -) => OverBuilder + builder: OverBuilder, +) => OverBuilder diff --git a/src/query-builder/case-builder.ts b/src/query-builder/case-builder.ts index 399bc4d6d..982e6838c 100644 --- a/src/query-builder/case-builder.ts +++ b/src/query-builder/case-builder.ts @@ -7,9 +7,14 @@ import { WhenNode } from '../operation-node/when-node.js' import { ComparisonOperatorExpression, OperandValueExpressionOrList, - parseWhen, + parseValueBinaryOperationOrExpression, } from '../parser/binary-operation-parser.js' -import { parseValueExpression } from '../parser/value-parser.js' +import { + ExtractTypeFromValueExpression, + isSafeImmediateValue, + parseSafeImmediateValue, + parseValueExpression, +} from '../parser/value-parser.js' import { KyselyTypeError } from '../util/type-error.js' export class CaseBuilder @@ -21,18 +26,23 @@ export class CaseBuilder this.#props = freeze(props) } - when>( + when< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( lhs: unknown extends W ? RE : KyselyTypeError<'when(lhs, op, rhs) is not supported when using case(value)'>, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: VE, ): CaseThenBuilder + when(expression: Expression): CaseThenBuilder + when( value: unknown extends W ? KyselyTypeError<'when(value) is only supported when using case(value)'> - : W + : W, ): CaseThenBuilder when(...args: any[]): any { @@ -40,7 +50,7 @@ export class CaseBuilder ...this.#props, node: CaseNode.cloneWithWhen( this.#props.node, - WhenNode.create(parseWhen(args)) + WhenNode.create(parseValueBinaryOperationOrExpression(args)), ), }) } @@ -63,7 +73,10 @@ export class CaseThenBuilder { * A `then` call can be followed by {@link Whenable.when}, {@link CaseWhenBuilder.else}, * {@link CaseWhenBuilder.end} or {@link CaseWhenBuilder.endCase} call. */ - then(expression: Expression): CaseWhenBuilder + then>( + expression: E, + ): CaseWhenBuilder> + then(value: V): CaseWhenBuilder then(valueExpression: any): any { @@ -71,14 +84,16 @@ export class CaseThenBuilder { ...this.#props, node: CaseNode.cloneWithThen( this.#props.node, - parseValueExpression(valueExpression) + isSafeImmediateValue(valueExpression) + ? parseSafeImmediateValue(valueExpression) + : parseValueExpression(valueExpression), ), }) } } export class CaseWhenBuilder - implements Whenable, Endable + implements Whenable, Endable { readonly #props: CaseBuilderProps @@ -86,18 +101,23 @@ export class CaseWhenBuilder this.#props = freeze(props) } - when>( + when< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( lhs: unknown extends W ? RE : KyselyTypeError<'when(lhs, op, rhs) is not supported when using case(value)'>, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: VE, ): CaseThenBuilder + when(expression: Expression): CaseThenBuilder + when( value: unknown extends W ? KyselyTypeError<'when(value) is only supported when using case(value)'> - : W + : W, ): CaseThenBuilder when(...args: any[]): any { @@ -105,7 +125,7 @@ export class CaseWhenBuilder ...this.#props, node: CaseNode.cloneWithWhen( this.#props.node, - WhenNode.create(parseWhen(args)) + WhenNode.create(parseValueBinaryOperationOrExpression(args)), ), }) } @@ -115,47 +135,54 @@ export class CaseWhenBuilder * * An `else` call must be followed by an {@link Endable.end} or {@link Endable.endCase} call. */ - else(expression: Expression): CaseEndBuilder - else(value: V): CaseEndBuilder + else>( + expression: E, + ): CaseEndBuilder> + + else(value: V): CaseEndBuilder else(valueExpression: any): any { return new CaseEndBuilder({ ...this.#props, node: CaseNode.cloneWith(this.#props.node, { - else: parseValueExpression(valueExpression), + else: isSafeImmediateValue(valueExpression) + ? parseSafeImmediateValue(valueExpression) + : parseValueExpression(valueExpression), }), }) } - end(): ExpressionWrapper { + end(): ExpressionWrapper { return new ExpressionWrapper( - CaseNode.cloneWith(this.#props.node, { isStatement: false }) + CaseNode.cloneWith(this.#props.node, { isStatement: false }), ) } - endCase(): ExpressionWrapper { + endCase(): ExpressionWrapper { return new ExpressionWrapper( - CaseNode.cloneWith(this.#props.node, { isStatement: true }) + CaseNode.cloneWith(this.#props.node, { isStatement: true }), ) } } -export class CaseEndBuilder implements Endable { +export class CaseEndBuilder + implements Endable +{ readonly #props: CaseBuilderProps constructor(props: CaseBuilderProps) { this.#props = freeze(props) } - end(): ExpressionWrapper { + end(): ExpressionWrapper { return new ExpressionWrapper( - CaseNode.cloneWith(this.#props.node, { isStatement: false }) + CaseNode.cloneWith(this.#props.node, { isStatement: false }), ) } - endCase(): ExpressionWrapper { + endCase(): ExpressionWrapper { return new ExpressionWrapper( - CaseNode.cloneWith(this.#props.node, { isStatement: true }) + CaseNode.cloneWith(this.#props.node, { isStatement: true }), ) } } @@ -166,12 +193,15 @@ interface Whenable { * * A `when` call must be followed by a {@link CaseThenBuilder.then} call. */ - when>( + when< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( lhs: unknown extends W ? RE : KyselyTypeError<'when(lhs, op, rhs) is not supported when using case(value)'>, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: VE, ): CaseThenBuilder when(expression: Expression): CaseThenBuilder @@ -179,18 +209,18 @@ interface Whenable { when( value: unknown extends W ? KyselyTypeError<'when(value) is only supported when using case(value)'> - : W + : W, ): CaseThenBuilder } -interface Endable { +interface Endable { /** * 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 + end(): ExpressionWrapper /** * Adds `end case` keywords to the case statement. @@ -198,5 +228,5 @@ interface Endable { * `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 + endCase(): ExpressionWrapper } diff --git a/src/query-builder/cte-builder.ts b/src/query-builder/cte-builder.ts new file mode 100644 index 000000000..b1d6013c3 --- /dev/null +++ b/src/query-builder/cte-builder.ts @@ -0,0 +1,54 @@ +import { OperationNodeSource } from '../operation-node/operation-node-source.js' +import { CommonTableExpressionNode } from '../operation-node/common-table-expression-node.js' +import { preventAwait } from '../util/prevent-await.js' +import { freeze } from '../util/object-utils.js' + +export class CTEBuilder implements OperationNodeSource { + readonly #props: CTEBuilderProps + + constructor(props: CTEBuilderProps) { + this.#props = freeze(props) + } + + /** + * Makes the common table expression materialized. + */ + materialized(): CTEBuilder { + return new CTEBuilder({ + ...this.#props, + node: CommonTableExpressionNode.cloneWith(this.#props.node, { + materialized: true, + }), + }) + } + + /** + * Makes the common table expression not materialized. + */ + notMaterialized(): CTEBuilder { + return new CTEBuilder({ + ...this.#props, + node: CommonTableExpressionNode.cloneWith(this.#props.node, { + materialized: false, + }), + }) + } + + toOperationNode(): CommonTableExpressionNode { + return this.#props.node + } +} + +preventAwait( + CTEBuilder, + "don't await CTEBuilder instances. They are never executed directly and are always just a part of a query.", +) + +interface CTEBuilderProps { + readonly node: CommonTableExpressionNode +} + +export type CTEBuilderCallback = ( + // N2 is needed for proper inference. Don't remove it. + cte: (name: N2) => CTEBuilder, +) => CTEBuilder diff --git a/src/query-builder/delete-query-builder.ts b/src/query-builder/delete-query-builder.ts index 9f75ea159..239a78991 100644 --- a/src/query-builder/delete-query-builder.ts +++ b/src/query-builder/delete-query-builder.ts @@ -17,8 +17,13 @@ import { parseSelectAll, SelectExpression, SelectArg, + SelectCallback, } from '../parser/select-parser.js' -import { ReturningAllRow, ReturningRow } from '../parser/returning-parser.js' +import { + ReturningAllRow, + ReturningCallbackRow, + ReturningRow, +} from '../parser/returning-parser.js' import { ReferenceExpression } from '../parser/reference-parser.js' import { QueryNode } from '../operation-node/query-node.js' import { @@ -28,6 +33,7 @@ import { ShallowRecord, SimplifyResult, SimplifySingleResult, + SqlBool, } from '../util/type-utils.js' import { preventAwait } from '../util/prevent-await.js' import { Compilable } from '../util/compilable.js' @@ -35,7 +41,7 @@ import { QueryExecutor } from '../query-executor/query-executor.js' import { QueryId } from '../util/query-id.js' import { freeze } from '../util/object-utils.js' import { KyselyPlugin } from '../plugin/kysely-plugin.js' -import { WhereExpressionFactory, WhereInterface } from './where-interface.js' +import { WhereInterface } from './where-interface.js' import { ReturningInterface } from './returning-interface.js' import { isNoResultErrorConstructor, @@ -55,21 +61,30 @@ import { AliasedExpression, Expression } from '../expression/expression.js' import { ComparisonOperatorExpression, OperandValueExpressionOrList, - parseReferentialComparison, - parseWhere, + parseValueBinaryOperationOrExpression, + parseReferentialBinaryOperation, } from '../parser/binary-operation-parser.js' -import { - ExistsExpression, - parseExists, - parseNotExists, -} from '../parser/unary-operation-parser.js' import { KyselyTypeError } from '../util/type-error.js' import { Streamable } from '../util/streamable.js' +import { ExpressionOrFactory } from '../parser/expression-parser.js' +import { + ValueExpression, + parseValueExpression, +} from '../parser/value-parser.js' +import { parseTop } from '../parser/top-parser.js' +import { + OutputCallback, + OutputExpression, + OutputInterface, + SelectExpressionFromOutputCallback, + SelectExpressionFromOutputExpression, +} from './output-interface.js' export class DeleteQueryBuilder implements WhereInterface, ReturningInterface, + OutputInterface, OperationNodeSource, Compilable, Explainable, @@ -81,125 +96,105 @@ export class DeleteQueryBuilder this.#props = freeze(props) } - where>( + where< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( lhs: RE, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: VE, ): DeleteQueryBuilder - where(factory: WhereExpressionFactory): DeleteQueryBuilder - - where(expression: Expression): DeleteQueryBuilder + where>( + expression: E, + ): DeleteQueryBuilder where(...args: any[]): any { return new DeleteQueryBuilder({ ...this.#props, queryNode: QueryNode.cloneWithWhere( this.#props.queryNode, - parseWhere(args) - ), - }) - } - - whereRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): DeleteQueryBuilder { - return new DeleteQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithWhere( - this.#props.queryNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - orWhere>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): DeleteQueryBuilder - - orWhere( - factory: WhereExpressionFactory - ): DeleteQueryBuilder - - orWhere(expression: Expression): DeleteQueryBuilder - - orWhere(...args: any[]): any { - return new DeleteQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithOrWhere( - this.#props.queryNode, - parseWhere(args) + parseValueBinaryOperationOrExpression(args), ), }) } - orWhereRef( - lhs: ReferenceExpression, + whereRef< + LRE extends ReferenceExpression, + RRE extends ReferenceExpression, + >( + lhs: LRE, op: ComparisonOperatorExpression, - rhs: ReferenceExpression + rhs: RRE, ): DeleteQueryBuilder { - return new DeleteQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithOrWhere( - this.#props.queryNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - whereExists(arg: ExistsExpression): DeleteQueryBuilder { return new DeleteQueryBuilder({ ...this.#props, queryNode: QueryNode.cloneWithWhere( this.#props.queryNode, - parseExists(arg) + parseReferentialBinaryOperation(lhs, op, rhs), ), }) } - whereNotExists(arg: ExistsExpression): DeleteQueryBuilder { - return new DeleteQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithWhere( - this.#props.queryNode, - parseNotExists(arg) - ), - }) - } - - orWhereExists(arg: ExistsExpression): DeleteQueryBuilder { - return new DeleteQueryBuilder({ + clearWhere(): DeleteQueryBuilder { + return new DeleteQueryBuilder({ ...this.#props, - queryNode: QueryNode.cloneWithOrWhere( - this.#props.queryNode, - parseExists(arg) - ), + queryNode: QueryNode.cloneWithoutWhere(this.#props.queryNode), }) } - orWhereNotExists( - arg: ExistsExpression + /** + * 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: number | bigint, + modifiers?: 'percent', ): DeleteQueryBuilder { return new DeleteQueryBuilder({ ...this.#props, - queryNode: QueryNode.cloneWithOrWhere( + queryNode: QueryNode.cloneWithTop( this.#props.queryNode, - parseNotExists(arg) + parseTop(expression, modifiers), ), }) } - clearWhere(): DeleteQueryBuilder { - return new DeleteQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithoutWhere(this.#props.queryNode), - }) - } - /** * Adds a `using` clause to the query. * @@ -275,11 +270,11 @@ export class DeleteQueryBuilder * ``` */ using>( - tables: TE[] + tables: TE[], ): DeleteQueryBuilder, FromTables, O> using>( - table: TE + table: TE, ): DeleteQueryBuilder, FromTables, O> using(tables: TableExpressionOrList): any { @@ -287,7 +282,7 @@ export class DeleteQueryBuilder ...this.#props, queryNode: DeleteQueryNode.cloneWithUsing( this.#props.queryNode, - parseTableExpressionOrList(tables) + parseTableExpressionOrList(tables), ), }) } @@ -404,12 +399,12 @@ export class DeleteQueryBuilder innerJoin< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression + K2 extends JoinReferenceExpression, >(table: TE, k1: K1, k2: K2): DeleteQueryBuilderWithInnerJoin innerJoin< TE extends TableExpression, - FN extends JoinCallbackExpression + FN extends JoinCallbackExpression, >(table: TE, callback: FN): DeleteQueryBuilderWithInnerJoin innerJoin(...args: any): any { @@ -417,7 +412,7 @@ export class DeleteQueryBuilder ...this.#props, queryNode: QueryNode.cloneWithJoin( this.#props.queryNode, - parseJoin('InnerJoin', args) + parseJoin('InnerJoin', args), ), }) } @@ -428,12 +423,12 @@ export class DeleteQueryBuilder leftJoin< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression + K2 extends JoinReferenceExpression, >(table: TE, k1: K1, k2: K2): DeleteQueryBuilderWithLeftJoin leftJoin< TE extends TableExpression, - FN extends JoinCallbackExpression + FN extends JoinCallbackExpression, >(table: TE, callback: FN): DeleteQueryBuilderWithLeftJoin leftJoin(...args: any): any { @@ -441,7 +436,7 @@ export class DeleteQueryBuilder ...this.#props, queryNode: QueryNode.cloneWithJoin( this.#props.queryNode, - parseJoin('LeftJoin', args) + parseJoin('LeftJoin', args), ), }) } @@ -452,12 +447,12 @@ export class DeleteQueryBuilder rightJoin< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression + K2 extends JoinReferenceExpression, >(table: TE, k1: K1, k2: K2): DeleteQueryBuilderWithRightJoin rightJoin< TE extends TableExpression, - FN extends JoinCallbackExpression + FN extends JoinCallbackExpression, >(table: TE, callback: FN): DeleteQueryBuilderWithRightJoin rightJoin(...args: any): any { @@ -465,7 +460,7 @@ export class DeleteQueryBuilder ...this.#props, queryNode: QueryNode.cloneWithJoin( this.#props.queryNode, - parseJoin('RightJoin', args) + parseJoin('RightJoin', args), ), }) } @@ -476,12 +471,12 @@ export class DeleteQueryBuilder fullJoin< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression + K2 extends JoinReferenceExpression, >(table: TE, k1: K1, k2: K2): DeleteQueryBuilderWithFullJoin fullJoin< TE extends TableExpression, - FN extends JoinCallbackExpression + FN extends JoinCallbackExpression, >(table: TE, callback: FN): DeleteQueryBuilderWithFullJoin fullJoin(...args: any): any { @@ -489,19 +484,31 @@ export class DeleteQueryBuilder ...this.#props, queryNode: QueryNode.cloneWithJoin( this.#props.queryNode, - parseJoin('FullJoin', args) + parseJoin('FullJoin', args), ), }) } returning>( - selection: SelectArg + selections: ReadonlyArray, + ): DeleteQueryBuilder> + + returning>( + callback: CB, + ): DeleteQueryBuilder> + + returning>( + selection: SE, + ): DeleteQueryBuilder> + + returning>( + selection: SelectArg, ): DeleteQueryBuilder> { return new DeleteQueryBuilder({ ...this.#props, queryNode: QueryNode.cloneWithReturning( this.#props.queryNode, - parseSelectArg(selection) + parseSelectArg(selection), ), }) } @@ -599,11 +606,11 @@ export class DeleteQueryBuilder * ``` */ returningAll( - tables: ReadonlyArray + tables: ReadonlyArray, ): DeleteQueryBuilder> returningAll( - table: T + table: T, ): DeleteQueryBuilder> returningAll(): DeleteQueryBuilder> @@ -612,12 +619,135 @@ export class DeleteQueryBuilder return new DeleteQueryBuilder({ ...this.#props, queryNode: QueryNode.cloneWithReturning( + this.#props.queryNode, + parseSelectAll(table), + ), + }) + } + + output>( + selections: readonly OE[] + ): DeleteQueryBuilder< + DB, + TB, + ReturningRow> + > + + output>( + callback: CB + ): DeleteQueryBuilder< + DB, + TB, + ReturningRow> + > + + output>( + selection: OE + ): DeleteQueryBuilder< + DB, + TB, + ReturningRow> + > + + output(args: any): any { + return new DeleteQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithOutput( + this.#props.queryNode, + parseSelectArg(args) + ), + }) + } + + outputAll( + table: 'deleted' + ): DeleteQueryBuilder> { + return new DeleteQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithOutput( this.#props.queryNode, parseSelectAll(table) ), }) } + /** + * Clears all `returning` clauses from the query. + * + * ### Examples + * + * ```ts + * db.deleteFrom('pet') + * .returningAll() + * .where('name', '=', 'Max') + * .clearReturning() + * ``` + * + * The generated SQL(PostgreSQL): + * + * ```sql + * delete from "pet" where "name" = "Max" + * ``` + */ + clearReturning(): DeleteQueryBuilder { + return new DeleteQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithoutReturning(this.#props.queryNode), + }) + } + + /** + * Clears the `limit` clause from the query. + * + * ### Examples + * + * ```ts + * db.deleteFrom('pet') + * .returningAll() + * .where('name', '=', 'Max') + * .limit(5) + * .clearLimit() + * ``` + * + * The generated SQL(PostgreSQL): + * + * ```sql + * delete from "pet" where "name" = "Max" returning * + * ``` + */ + clearLimit(): DeleteQueryBuilder { + return new DeleteQueryBuilder({ + ...this.#props, + queryNode: DeleteQueryNode.cloneWithoutLimit(this.#props.queryNode), + }) + } + + /** + * Clears the `order by` clause from the query. + * + * ### Examples + * + * ```ts + * db.deleteFrom('pet') + * .returningAll() + * .where('name', '=', 'Max') + * .orderBy('id') + * .clearOrderBy() + * ``` + * + * The generated SQL(PostgreSQL): + * + * ```sql + * delete from "pet" where "name" = "Max" returning * + * ``` + */ + clearOrderBy(): DeleteQueryBuilder { + return new DeleteQueryBuilder({ + ...this.#props, + queryNode: DeleteQueryNode.cloneWithoutOrderBy(this.#props.queryNode), + }) + } + /** * Adds an `order by` clause to the query. * @@ -654,13 +784,13 @@ export class DeleteQueryBuilder */ orderBy( orderBy: OrderByExpression, - direction?: OrderByDirectionExpression + direction?: OrderByDirectionExpression, ): DeleteQueryBuilder { return new DeleteQueryBuilder({ ...this.#props, - queryNode: DeleteQueryNode.cloneWithOrderByItem( + queryNode: DeleteQueryNode.cloneWithOrderByItems( this.#props.queryNode, - parseOrderBy(orderBy, direction) + parseOrderBy([orderBy, direction]), ), }) } @@ -683,12 +813,12 @@ export class DeleteQueryBuilder * .execute() * ``` */ - limit(limit: number): DeleteQueryBuilder { + limit(limit: ValueExpression): DeleteQueryBuilder { return new DeleteQueryBuilder({ ...this.#props, queryNode: DeleteQueryNode.cloneWithLimit( this.#props.queryNode, - LimitNode.create(limit) + LimitNode.create(parseValueExpression(limit)), ), }) } @@ -719,13 +849,6 @@ export class DeleteQueryBuilder return func(this) } - /** - * @deprecated Use `$call` instead - */ - call(func: (qb: this) => T): T { - return this.$call(func) - } - /** * Call `func(this)` if `condition` is true. * @@ -763,7 +886,7 @@ export class DeleteQueryBuilder */ $if( condition: boolean, - func: (qb: this) => DeleteQueryBuilder + func: (qb: this) => DeleteQueryBuilder, ): O2 extends DeleteResult ? DeleteQueryBuilder : O2 extends O & infer E @@ -778,37 +901,16 @@ export class DeleteQueryBuilder }) as any } - /** - * @deprecated Use `$if` instead - */ - if( - condition: boolean, - func: (qb: this) => DeleteQueryBuilder - ): O2 extends DeleteResult - ? DeleteQueryBuilder - : O2 extends O & infer E - ? DeleteQueryBuilder> - : DeleteQueryBuilder> { - return this.$if(condition, func) - } - /** * Change the output type of the query. * - * You should only use this method as the last resort if the types - * don't support your use case. + * 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(): DeleteQueryBuilder { + $castTo(): DeleteQueryBuilder { return new DeleteQueryBuilder(this.#props) } - /** - * @deprecated Use `$castTo` instead. - */ - castTo(): DeleteQueryBuilder { - return this.$castTo() - } - /** * Narrows (parts of) the output type of the query. * @@ -901,15 +1003,6 @@ export class DeleteQueryBuilder return new DeleteQueryBuilder(this.#props) as unknown as any } - /** - * @deprecated Use `$assertType` instead. - */ - assertType(): O extends T - ? DeleteQueryBuilder - : KyselyTypeError<`assertType() call failed: The type passed in is not equal to the output type of the query.`> { - return new DeleteQueryBuilder(this.#props) as unknown as any - } - /** * Returns a copy of this DeleteQueryBuilder instance with the given plugin installed. */ @@ -923,14 +1016,14 @@ export class DeleteQueryBuilder toOperationNode(): DeleteQueryNode { return this.#props.executor.transformQuery( this.#props.queryNode, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery> { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -941,21 +1034,26 @@ export class DeleteQueryBuilder */ async execute(): Promise[]> { const compiledQuery = this.compile() - const query = compiledQuery.query as DeleteQueryNode const result = await this.#props.executor.executeQuery( compiledQuery, - this.#props.queryId + this.#props.queryId, ) - if (this.#props.executor.adapter.supportsReturning && query.returning) { + const { adapter } = this.#props.executor + const query = compiledQuery.query as DeleteQueryNode + + if ( + (query.returning && adapter.supportsReturning) || + (query.output && adapter.supportsOutput) + ) { return result.rows as any } return [ new DeleteResult( // TODO: remove numUpdatedOrDeletedRows. - result.numAffectedRows ?? result.numUpdatedOrDeletedRows ?? BigInt(0) + result.numAffectedRows ?? result.numUpdatedOrDeletedRows ?? BigInt(0), ) as any, ] } @@ -980,7 +1078,7 @@ export class DeleteQueryBuilder async executeTakeFirstOrThrow( errorConstructor: | NoResultErrorConstructor - | ((node: QueryNode) => Error) = NoResultError + | ((node: QueryNode) => Error) = NoResultError, ): Promise> { const result = await this.executeTakeFirst() @@ -1001,7 +1099,7 @@ export class DeleteQueryBuilder const stream = this.#props.executor.stream( compiledQuery, chunkSize, - this.#props.queryId + this.#props.queryId, ) for await (const item of stream) { @@ -1011,14 +1109,14 @@ export class DeleteQueryBuilder async explain = Record>( format?: ExplainFormat, - options?: Expression + options?: Expression, ): Promise { const builder = new DeleteQueryBuilder({ ...this.#props, queryNode: QueryNode.cloneWithExplain( this.#props.queryNode, format, - options + options, ), }) @@ -1028,7 +1126,7 @@ export class DeleteQueryBuilder preventAwait( DeleteQueryBuilder, - "don't await DeleteQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`." + "don't await DeleteQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`.", ) export interface DeleteQueryBuilderProps { @@ -1041,7 +1139,7 @@ export type DeleteQueryBuilderWithInnerJoin< DB, TB extends keyof DB, O, - TE extends TableExpression + TE extends TableExpression, > = TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? InnerJoinedBuilder @@ -1059,7 +1157,7 @@ type InnerJoinedBuilder< TB extends keyof DB, O, A extends string, - R + R, > = A extends keyof DB ? DeleteQueryBuilder, TB | A, O> : // Much faster non-recursive solution for the simple case. @@ -1073,7 +1171,7 @@ export type DeleteQueryBuilderWithLeftJoin< DB, TB extends keyof DB, O, - TE extends TableExpression + TE extends TableExpression, > = TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? LeftJoinedBuilder @@ -1091,7 +1189,7 @@ type LeftJoinedBuilder< TB extends keyof DB, O, A extends keyof any, - R + R, > = A extends keyof DB ? DeleteQueryBuilder, TB | A, O> : // Much faster non-recursive solution for the simple case. @@ -1109,7 +1207,7 @@ export type DeleteQueryBuilderWithRightJoin< DB, TB extends keyof DB, O, - TE extends TableExpression + TE extends TableExpression, > = TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? RightJoinedBuilder @@ -1127,14 +1225,14 @@ type RightJoinedBuilder< TB extends keyof DB, O, A extends keyof any, - R + R, > = DeleteQueryBuilder, TB | A, O> type RightJoinedDB< DB, TB extends keyof DB, A extends keyof any, - R + R, > = DrainOuterGeneric<{ [C in keyof DB | A]: C extends A ? R @@ -1149,7 +1247,7 @@ export type DeleteQueryBuilderWithFullJoin< DB, TB extends keyof DB, O, - TE extends TableExpression + TE extends TableExpression, > = TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? OuterJoinedBuilder @@ -1167,14 +1265,14 @@ type OuterJoinedBuilder< TB extends keyof DB, O, A extends keyof any, - R + R, > = DeleteQueryBuilder, TB | A, O> type OuterJoinedBuilderDB< DB, TB extends keyof DB, A extends keyof any, - R + R, > = DrainOuterGeneric<{ [C in keyof DB | A]: C extends A ? Nullable diff --git a/src/query-builder/deprecated-having-expression-builder.ts b/src/query-builder/deprecated-having-expression-builder.ts deleted file mode 100644 index e245588e1..000000000 --- a/src/query-builder/deprecated-having-expression-builder.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { Expression } from '../expression/expression.js' -import { OperationNode } from '../operation-node/operation-node.js' -import { - ComparisonOperatorExpression, - OperandValueExpressionOrList, -} from '../parser/binary-operation-parser.js' -import { ReferenceExpression } from '../parser/reference-parser.js' -import { ExistsExpression } from '../parser/unary-operation-parser.js' -import { ExpressionBuilder } from '../expression/expression-builder.js' - -/** - * Temporary transitional wrapper type that contains the old `HavingGrouper` methods - * and the new `ExpressionBuilder` interface. One we remove the deprecated methods, - * this interface can be ditched in favor of just `ExpressionBuilder`. - */ -export interface HavingExpressionBuilder - extends ExpressionBuilder { - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - having>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): HavingExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - having( - grouper: HavingExpressionBuilder - ): HavingExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - having(expression: Expression): HavingExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - havingRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): HavingExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orHaving>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): HavingExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orHaving( - grouper: HavingExpressionBuilder - ): HavingExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orHaving(expression: Expression): HavingExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orHavingRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): HavingExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - havingExists(arg: ExistsExpression): HavingExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - havingNotExists( - arg: ExistsExpression - ): HavingExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orHavingExists(arg: ExistsExpression): HavingExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orHavingNotExists( - arg: ExistsExpression - ): HavingExpressionBuilder - - toOperationNode(): OperationNode -} diff --git a/src/query-builder/deprecated-on-expression-builder.ts b/src/query-builder/deprecated-on-expression-builder.ts deleted file mode 100644 index 13f915991..000000000 --- a/src/query-builder/deprecated-on-expression-builder.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Expression } from '../expression/expression.js' -import { OperationNode } from '../operation-node/operation-node.js' -import { - ComparisonOperatorExpression, - OperandValueExpressionOrList, -} from '../parser/binary-operation-parser.js' -import { ReferenceExpression } from '../parser/reference-parser.js' -import { ExistsExpression } from '../parser/unary-operation-parser.js' -import { ExpressionBuilder } from '../expression/expression-builder.js' - -/** - * Temporary transitional wrapper type that contains the old `OnGrouper` methods - * and the new `ExpressionBuilder` interface. One we remove the deprecated methods, - * this interface can be ditched in favor of just `ExpressionBuilder`. - */ -export interface OnExpressionBuilder - extends ExpressionBuilder { - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - on>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): OnExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - on(grouper: OnExpressionBuilder): OnExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - on(expression: Expression): OnExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - onRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): OnExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orOn>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): OnExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orOn(grouper: OnExpressionBuilder): OnExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orOn(expression: Expression): OnExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orOnRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): OnExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - onExists(arg: ExistsExpression): OnExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - onNotExists(arg: ExistsExpression): OnExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orOnExists(arg: ExistsExpression): OnExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orOnNotExists(arg: ExistsExpression): OnExpressionBuilder - - toOperationNode(): OperationNode -} diff --git a/src/query-builder/deprecated-where-expression-builder.ts b/src/query-builder/deprecated-where-expression-builder.ts deleted file mode 100644 index d0599333d..000000000 --- a/src/query-builder/deprecated-where-expression-builder.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Expression } from '../expression/expression.js' -import { OperationNode } from '../operation-node/operation-node.js' -import { - ComparisonOperatorExpression, - OperandValueExpressionOrList, -} from '../parser/binary-operation-parser.js' -import { ReferenceExpression } from '../parser/reference-parser.js' -import { ExistsExpression } from '../parser/unary-operation-parser.js' -import { ExpressionBuilder } from '../expression/expression-builder.js' - -/** - * Temporary transitional wrapper type that contains the old `WhereGrouper` methods - * and the new `ExpressionBuilder` interface. One we remove the deprecated methods, - * this interface can be ditched in favor of just `ExpressionBuilder`. - */ -export interface WhereExpressionBuilder - extends ExpressionBuilder { - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - where>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): WhereExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - where(grouper: WhereExpressionBuilder): WhereExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - where(expression: Expression): WhereExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - whereRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): WhereExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): WhereExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere( - grouper: WhereExpressionBuilder - ): WhereExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere(expression: Expression): WhereExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhereRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): WhereExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - whereExists(arg: ExistsExpression): WhereExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - whereNotExists(arg: ExistsExpression): WhereExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhereExists(arg: ExistsExpression): WhereExpressionBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhereNotExists( - arg: ExistsExpression - ): WhereExpressionBuilder - - toOperationNode(): OperationNode -} diff --git a/src/query-builder/function-module.ts b/src/query-builder/function-module.ts index 84dd90092..dda74d9f1 100644 --- a/src/query-builder/function-module.ts +++ b/src/query-builder/function-module.ts @@ -1,18 +1,29 @@ -import { DynamicReferenceBuilder } from '../dynamic/dynamic-reference-builder.js' import { ExpressionWrapper } from '../expression/expression-wrapper.js' +import { Expression } from '../expression/expression.js' import { AggregateFunctionNode } from '../operation-node/aggregate-function-node.js' import { FunctionNode } from '../operation-node/function-node.js' -import { CoalesceReferenceExpressionList } from '../parser/coalesce-parser.js' +import { + ExtractTypeFromCoalesce1, + ExtractTypeFromCoalesce3, + ExtractTypeFromCoalesce2, + ExtractTypeFromCoalesce4, + ExtractTypeFromCoalesce5, +} from '../parser/coalesce-parser.js' import { ExtractTypeFromReferenceExpression, - SimpleReferenceExpression, ReferenceExpression, StringReference, parseReferenceExpressionOrList, + ExtractTypeFromStringReference, } from '../parser/reference-parser.js' import { parseSelectAll } from '../parser/select-parser.js' -import { Equals, IsAny } from '../util/type-utils.js' +import { KyselyTypeError } from '../util/type-error.js' +import { IsNever } from '../util/type-utils.js' import { AggregateFunctionBuilder } from './aggregate-function-builder.js' +import { SelectQueryBuilderExpression } from '../query-builder/select-query-builder-expression.js' +import { isString } from '../util/object-utils.js' +import { parseTable } from '../parser/table-parser.js' +import { Selectable } from '../util/column-type.js' /** * Helpers for type safe SQL function calls. @@ -24,21 +35,47 @@ import { AggregateFunctionBuilder } from './aggregate-function-builder.js' * * * - * This example uses the `fn` module to select some aggregates: + * 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 }) => [ + * .select(({ fn, val, ref }) => [ * 'person.id', * * // The `fn` module contains the most common * // functions. * fn.count('pet.id').as('pet_count'), * - * // You can call any function using the - * // `agg` method - * fn.agg('array_agg', ['pet.name']).as('pet_names') + * // 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('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('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`concat( + * ${ref('first_name')}, + * ' ', + * ${ref('last_name')} + * )`.as('full_name') * ]) * .groupBy('person.id') * .having((eb) => eb.fn.count('pet.id'), '>', 10) @@ -51,11 +88,13 @@ import { AggregateFunctionBuilder } from './aggregate-function-builder.js' * select * "person"."id", * count("pet"."id") as "pet_count", - * array_agg("pet"."name") as "pet_names" + * 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") > $1 + * having count("pet"."id") > $3 * ``` */ export interface FunctionModule { @@ -85,13 +124,13 @@ export interface FunctionModule { * ```ts * db.selectFrom('person') * .selectAll('person') - * .where(sql`upper(first_name)`, '=', 'JENNIFER') + * .where(sql`upper(first_name)`, '=', 'JENNIFER') * ``` */ - ( + = ReferenceExpression>( name: string, - args: ReadonlyArray> - ): ExpressionWrapper + args?: ReadonlyArray, + ): ExpressionWrapper /** * Creates an aggregate function call. @@ -121,13 +160,13 @@ export interface FunctionModule { * from "person" * ``` */ - agg( + agg = ReferenceExpression>( name: string, - args?: ReadonlyArray> + args?: ReadonlyArray, ): AggregateFunctionBuilder /** - * Calls the `avg` function for the column given as the argument. + * Calls the `avg` function for the column or expression given as the argument. * * This sql function calculates the average value for a given column. * @@ -138,10 +177,8 @@ export interface FunctionModule { * ### Examples * * ```ts - * const { avg } = db.fn - * * db.selectFrom('toy') - * .select(avg('price').as('avg_price')) + * .select((eb) => eb.fn.avg('price').as('avg_price')) * .execute() * ``` * @@ -170,10 +207,8 @@ export interface FunctionModule { * the first type argument: * * ```ts - * const { avg } = db.fn - * * db.selectFrom('toy') - * .select(avg('price').as('avg_price')) + * .select((eb) => eb.fn.avg('price').as('avg_price')) * .execute() * ``` * @@ -183,18 +218,16 @@ export interface FunctionModule { * function. * * ```ts - * const { avg } = db.fn - * * db.selectFrom('toy') - * .select(avg('price').as('avg_price')) + * .select((eb) => eb.fn.avg('price').as('avg_price')) * .execute() * ``` */ avg< O extends number | string | null = number | string, - C extends ReferenceExpression = ReferenceExpression + RE extends ReferenceExpression = ReferenceExpression, >( - column: C + expr: RE, ): AggregateFunctionBuilder /** @@ -218,10 +251,8 @@ export interface FunctionModule { * ### Examples * * ```ts - * const { coalesce } = db.fn - * * db.selectFrom('participant') - * .select(coalesce('nickname', sql`''`).as('nickname')) + * .select((eb) => eb.fn.coalesce('nickname', sql`''`).as('nickname')) * .where('room_id', '=', roomId) * .execute() * ``` @@ -247,10 +278,8 @@ export interface FunctionModule { * You can combine this function with other helpers in this module: * * ```ts - * const { avg, coalesce } = db.fn - * * db.selectFrom('person') - * .select(coalesce(avg('age'), sql`0`).as('avg_age')) + * .select((eb) => eb.fn.coalesce(eb.fn.avg('age'), sql`0`).as('avg_age')) * .where('first_name', '=', 'Jennifer') * .execute() * ``` @@ -261,16 +290,60 @@ export interface FunctionModule { * select coalesce(avg("age"), 0) as "avg_age" from "person" where "first_name" = $1 * ``` */ + coalesce>( + v1: V1, + ): ExpressionWrapper> + + coalesce< + V1 extends ReferenceExpression, + V2 extends ReferenceExpression, + >( + v1: V1, + v2: V2, + ): ExpressionWrapper> + + coalesce< + V1 extends ReferenceExpression, + V2 extends ReferenceExpression, + V3 extends ReferenceExpression, + >( + v1: V1, + v2: V2, + v3: V3, + ): ExpressionWrapper> + + coalesce< + V1 extends ReferenceExpression, + V2 extends ReferenceExpression, + V3 extends ReferenceExpression, + V4 extends ReferenceExpression, + >( + v1: V1, + v2: V2, + v3: V3, + v4: V4, + ): ExpressionWrapper> + coalesce< - V extends ReferenceExpression, - OV extends ReferenceExpression[] + V1 extends ReferenceExpression, + V2 extends ReferenceExpression, + V3 extends ReferenceExpression, + V4 extends ReferenceExpression, + V5 extends ReferenceExpression, >( - value: V, - ...otherValues: OV - ): ExpressionWrapper> + v1: V1, + v2: V2, + v3: V3, + v4: V4, + v5: V5, + ): ExpressionWrapper< + DB, + TB, + ExtractTypeFromCoalesce5 + > /** - * Calls the `count` function for the column given as the argument. + * 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. @@ -284,10 +357,8 @@ export interface FunctionModule { * ### Examples * * ```ts - * const { count } = db.fn - * * db.selectFrom('toy') - * .select(count('id').as('num_toys')) + * .select((eb) => eb.fn.count('id').as('num_toys')) * .execute() * ``` * @@ -308,10 +379,8 @@ export interface FunctionModule { * the type as the first type argument: * * ```ts - * const { count } = db.fn - * * db.selectFrom('toy') - * .select(count('id').as('num_toys')) + * .select((eb) => eb.fn.count('id').as('num_toys')) * .execute() * ``` * @@ -325,9 +394,9 @@ export interface FunctionModule { */ count< O extends number | string | bigint, - C extends ReferenceExpression = ReferenceExpression + RE extends ReferenceExpression = ReferenceExpression, >( - column: C + expr: RE, ): AggregateFunctionBuilder /** @@ -346,10 +415,8 @@ export interface FunctionModule { * ### Examples * * ```ts - * const { countAll } = db.fn - * * db.selectFrom('toy') - * .select(countAll().as('num_toys')) + * .select((eb) => eb.fn.countAll().as('num_toys')) * .execute() * ``` * @@ -370,10 +437,8 @@ export interface FunctionModule { * the type as the first type argument: * * ```ts - * const { countAll } = db.fn - * * db.selectFrom('toy') - * .select(countAll().as('num_toys')) + * .select((eb) => eb.fn.countAll().as('num_toys')) * .execute() * ``` * @@ -381,11 +446,9 @@ export interface FunctionModule { * table: * * ```ts - * const { countAll } = db.fn - * * db.selectFrom('toy') * .innerJoin('pet', 'pet.id', 'toy.pet_id') - * .select(countAll('toy').as('num_toys')) + * .select((eb) => eb.fn.countAll('toy').as('num_toys')) * .execute() * ``` * @@ -406,7 +469,7 @@ export interface FunctionModule { * ``` */ countAll( - table: T + table: T, ): AggregateFunctionBuilder countAll(): AggregateFunctionBuilder< @@ -416,7 +479,7 @@ export interface FunctionModule { > /** - * Calls the `max` function for the column given as the argument. + * Calls the `max` function for the column or expression given as the argument. * * This sql function calculates the maximum value for a given column. * @@ -431,10 +494,8 @@ export interface FunctionModule { * ### Examples * * ```ts - * const { max } = db.fn - * * db.selectFrom('toy') - * .select(max('price').as('max_price')) + * .select((eb) => eb.fn.max('price').as('max_price')) * .execute() * ``` * @@ -458,26 +519,26 @@ export interface FunctionModule { * function. * * ```ts - * const { max } = db.fn - * * db.selectFrom('toy') - * .select(max('price').as('max_price')) + * .select((eb) => eb.fn.max('price').as('max_price')) * .execute() * ``` */ max< - O extends number | string | bigint | null = any, - C extends StringReference = StringReference + O extends number | string | bigint | null = never, + RE extends ReferenceExpression = ReferenceExpression, >( - column: OutputBoundStringReference - ): StringReferenceBoundAggregateFunctionBuilder - - max( - column: DynamicReferenceBuilder - ): AggregateFunctionBuilder + expr: RE, + ): AggregateFunctionBuilder< + DB, + TB, + IsNever extends true + ? ExtractTypeFromReferenceExpression + : O + > /** - * Calls the `min` function for the column given as the argument. + * Calls the `min` function for the column or expression given as the argument. * * This sql function calculates the minimum value for a given column. * @@ -492,10 +553,8 @@ export interface FunctionModule { * ### Examples * * ```ts - * const { min } = db.fn - * * db.selectFrom('toy') - * .select(min('price').as('min_price')) + * .select((eb) => eb.fn.min('price').as('min_price')) * .execute() * ``` * @@ -519,26 +578,26 @@ export interface FunctionModule { * function. * * ```ts - * const { min } = db.fn - * * db.selectFrom('toy') - * .select(min('price').as('min_price')) + * .select((eb) => eb.fn.min('price').as('min_price')) * .execute() * ``` */ min< - O extends number | string | bigint | null = any, - C extends StringReference = StringReference + O extends number | string | bigint | null = never, + RE extends ReferenceExpression = ReferenceExpression, >( - column: OutputBoundStringReference - ): StringReferenceBoundAggregateFunctionBuilder - - min( - column: DynamicReferenceBuilder - ): AggregateFunctionBuilder + expr: RE, + ): AggregateFunctionBuilder< + DB, + TB, + IsNever extends true + ? ExtractTypeFromReferenceExpression + : O + > /** - * Calls the `sum` function for the column given as the argument. + * Calls the `sum` function for the column or expression given as the argument. * * This sql function sums the values of a given column. * @@ -549,10 +608,8 @@ export interface FunctionModule { * ### Examples * * ```ts - * const { sum } = db.fn - * * db.selectFrom('toy') - * .select(sum('price').as('total_price')) + * .select((eb) => eb.fn.sum('price').as('total_price')) * .execute() * ``` * @@ -581,10 +638,8 @@ export interface FunctionModule { * the first type argument: * * ```ts - * const { sum } = db.fn - * * db.selectFrom('toy') - * .select(sum('price').as('total_price')) + * .select((eb) => eb.fn.sum('price').as('total_price')) * .execute() * ``` * @@ -594,19 +649,123 @@ export interface FunctionModule { * function. * * ```ts - * const { sum } = db.fn - * * db.selectFrom('toy') - * .select(sum('price').as('total_price')) + * .select((eb) => eb.fn.sum('price').as('total_price')) * .execute() * ``` */ sum< O extends number | string | bigint | null = number | string | bigint, - C extends ReferenceExpression = ReferenceExpression + RE extends ReferenceExpression = ReferenceExpression, >( - column: C + expr: RE, ): AggregateFunctionBuilder + + /** + * 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 + * db.selectFrom('person') + * .selectAll('person') + * .where((eb) => eb( + * eb.val('Jen'), '=', eb.fn.any('person.nicknames') + * )) + * ``` + * + * + * The generated SQL (PostgreSQL): + * + * ```sql + * select + * "person".* + * from + * "person" + * where + * $1 = any("person"."nicknames") + * ``` + */ + any>( + expr: RE, + ): Exclude< + ExtractTypeFromStringReference, + null + > extends ReadonlyArray + ? ExpressionWrapper + : KyselyTypeError<'any(expr) call failed: expr must be an array'> + + any( + subquery: SelectQueryBuilderExpression>, + ): ExpressionWrapper + + any(expr: Expression>): ExpressionWrapper + + /** + * Creates a json_agg function call. + * + * This function is only available on PostgreSQL. + * + * ```ts + * 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" + * ``` + */ + jsonAgg>( + table: T, + ): AggregateFunctionBuilder< + DB, + TB, + T extends TB + ? Selectable[] + : T extends Expression + ? O[] + : never + > + + /** + * Creates a to_json function call. + * + * This function is only available on PostgreSQL. + * + * ```ts + * 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>( + table: T, + ): ExpressionWrapper< + DB, + TB, + T extends TB ? Selectable : T extends Expression ? O : never + > } export function createFunctionModule(): FunctionModule< @@ -615,21 +774,21 @@ export function createFunctionModule(): FunctionModule< > { const fn = ( name: string, - args: ReadonlyArray> - ): ExpressionWrapper => { + args?: ReadonlyArray>, + ): ExpressionWrapper => { return new ExpressionWrapper( - FunctionNode.create(name, parseReferenceExpressionOrList(args)) + FunctionNode.create(name, parseReferenceExpressionOrList(args ?? [])), ) } const agg = ( name: string, - args?: ReadonlyArray> + args?: ReadonlyArray>, ): AggregateFunctionBuilder => { return new AggregateFunctionBuilder({ aggregateFunctionNode: AggregateFunctionNode.create( name, - args ? parseReferenceExpressionOrList(args) : undefined + args ? parseReferenceExpressionOrList(args) : undefined, ), }) } @@ -639,24 +798,18 @@ export function createFunctionModule(): FunctionModule< avg< O extends number | string | null = number | string, - C extends ReferenceExpression = ReferenceExpression + C extends ReferenceExpression = ReferenceExpression, >(column: C): AggregateFunctionBuilder { return agg('avg', [column]) }, - coalesce< - V extends ReferenceExpression, - OV extends ReferenceExpression[] - >( - value: V, - ...otherValues: OV - ): ExpressionWrapper> { - return fn('coalesce', [value, ...otherValues]) + coalesce(...values: any[]): ExpressionWrapper { + return fn('coalesce', values) }, count< O extends number | string | bigint, - C extends ReferenceExpression = ReferenceExpression + C extends ReferenceExpression = ReferenceExpression, >(column: C): AggregateFunctionBuilder { return agg('count', [column]) }, @@ -665,60 +818,44 @@ export function createFunctionModule(): FunctionModule< return new AggregateFunctionBuilder({ aggregateFunctionNode: AggregateFunctionNode.create( 'count', - parseSelectAll(table) + parseSelectAll(table), ), }) }, - max< - C extends SimpleReferenceExpression = SimpleReferenceExpression< - DB, - TB - > - >(column: C): any { + max(column: any): any { return agg('max', [column]) }, - min< - C extends SimpleReferenceExpression = SimpleReferenceExpression< - DB, - TB - > - >(column: C): any { + min(column: any): any { return agg('min', [column]) }, sum< O extends number | string | bigint | null = number | string | bigint, - C extends ReferenceExpression = ReferenceExpression + C extends ReferenceExpression = ReferenceExpression, >(column: C): AggregateFunctionBuilder { return agg('sum', [column]) }, + + any>(column: RE): any { + return fn('any', [column]) + }, + + jsonAgg(table: string | Expression): any { + return new AggregateFunctionBuilder({ + aggregateFunctionNode: AggregateFunctionNode.create('json_agg', [ + isString(table) ? parseTable(table) : table.toOperationNode(), + ]), + }) + }, + + toJson(table: string | Expression): any { + return new ExpressionWrapper( + FunctionNode.create('to_json', [ + isString(table) ? parseTable(table) : table.toOperationNode(), + ]), + ) + }, }) } - -type OutputBoundStringReference< - DB, - TB extends keyof DB, - C extends StringReference, - O -> = IsAny extends true - ? C // output not provided, unbound - : Equals< - ExtractTypeFromReferenceExpression | null, - O | null - > extends true - ? C - : never - -type StringReferenceBoundAggregateFunctionBuilder< - DB, - TB extends keyof DB, - C extends StringReference, - O -> = AggregateFunctionBuilder< - DB, - TB, - | ExtractTypeFromReferenceExpression - | (IsAny extends true ? never : null extends O ? null : never) // output is nullable, but column type might not be nullable. -> diff --git a/src/query-builder/having-interface.ts b/src/query-builder/having-interface.ts index b0b085a34..2ecef4866 100644 --- a/src/query-builder/having-interface.ts +++ b/src/query-builder/having-interface.ts @@ -1,86 +1,37 @@ -import { Expression } from '../expression/expression.js' import { ComparisonOperatorExpression, OperandValueExpressionOrList, } from '../parser/binary-operation-parser.js' +import { ExpressionOrFactory } from '../parser/expression-parser.js' import { ReferenceExpression } from '../parser/reference-parser.js' -import { ExistsExpression } from '../parser/unary-operation-parser.js' import { SqlBool } from '../util/type-utils.js' -import { HavingExpressionBuilder } from './deprecated-having-expression-builder.js' export interface HavingInterface { /** * Just like {@link WhereInterface.where | where} but adds a `having` statement * instead of a `where` statement. */ - having>( + having< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( lhs: RE, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: VE, ): HavingInterface - having(factory: HavingExpressionFactory): HavingInterface - having(expression: Expression): HavingInterface + having(expression: E): HavingInterface /** * Just like {@link WhereInterface.whereRef | whereRef} but adds a `having` statement * instead of a `where` statement. */ - havingRef( - lhs: ReferenceExpression, + havingRef< + LRE extends ReferenceExpression, + RRE extends ReferenceExpression, + >( + lhs: LRE, op: ComparisonOperatorExpression, - rhs: ReferenceExpression + rhs: RRE, ): HavingInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orHaving>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): HavingInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orHaving(factory: HavingExpressionFactory): HavingInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orHaving(expression: Expression): HavingInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orHavingRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): HavingInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - havingExists(arg: ExistsExpression): HavingInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - havingNotExists(arg: ExistsExpression): HavingInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orHavingExists(arg: ExistsExpression): HavingInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orHavingNotExists(arg: ExistsExpression): HavingInterface } - -export type HavingExpressionFactory = ( - eb: HavingExpressionBuilder -) => Expression | HavingExpressionBuilder diff --git a/src/query-builder/insert-query-builder.ts b/src/query-builder/insert-query-builder.ts index ba5d86e10..e40905128 100644 --- a/src/query-builder/insert-query-builder.ts +++ b/src/query-builder/insert-query-builder.ts @@ -5,11 +5,10 @@ import { parseSelectAll, SelectExpression, SelectArg, + SelectCallback, } from '../parser/select-parser.js' import { InsertExpression, - InsertObjectOrList, - InsertObjectOrListFactory, parseInsertExpression, } from '../parser/insert-values-parser.js' import { InsertQueryNode } from '../operation-node/insert-query-node.js' @@ -20,8 +19,8 @@ import { SimplifySingleResult, } from '../util/type-utils.js' import { - UpdateExpression, - parseUpdateExpression, + UpdateObjectExpression, + parseUpdateObjectExpression, } from '../parser/update-set-parser.js' import { preventAwait } from '../util/prevent-await.js' import { Compilable } from '../util/compilable.js' @@ -31,7 +30,11 @@ import { freeze } from '../util/object-utils.js' import { OnDuplicateKeyNode } from '../operation-node/on-duplicate-key-node.js' import { InsertResult } from './insert-result.js' import { KyselyPlugin } from '../plugin/kysely-plugin.js' -import { ReturningRow } from '../parser/returning-parser.js' +import { + ReturningAllRow, + ReturningCallbackRow, + ReturningRow, +} from '../parser/returning-parser.js' import { isNoResultErrorConstructor, NoResultError, @@ -45,7 +48,9 @@ import { ColumnNode } from '../operation-node/column-node.js' import { ReturningInterface } from './returning-interface.js' import { OnConflictBuilder, + OnConflictDatabase, OnConflictDoNothingBuilder, + OnConflictTables, OnConflictUpdateBuilder, } from './on-conflict-builder.js' import { OnConflictNode } from '../operation-node/on-conflict-node.js' @@ -54,10 +59,19 @@ import { Explainable, ExplainFormat } from '../util/explainable.js' import { Expression } from '../expression/expression.js' import { KyselyTypeError } from '../util/type-error.js' import { Streamable } from '../util/streamable.js' +import { parseTop } from '../parser/top-parser.js' +import { + OutputCallback, + OutputExpression, + OutputInterface, + SelectExpressionFromOutputCallback, + SelectExpressionFromOutputExpression, +} from './output-interface.js' export class InsertQueryBuilder implements ReturningInterface, + OutputInterface, OperationNodeSource, Compilable, Explainable, @@ -105,13 +119,18 @@ export class InsertQueryBuilder * }) * .executeTakeFirst() * + * // `insertId` is only available on dialects that + * // automatically return the id of the inserted row + * // such as MySQL and SQLite. On PostgreSQL, for example, + * // you need to add a `returning` clause to the query to + * // get anything out. See the "returning data" example. * console.log(result.insertId) * ``` * - * The generated SQL (PostgreSQL): + * The generated SQL (MySQL): * * ```sql - * insert into "person" ("first_name", "last_name", "age") values ($1, $2, $3) + * insert into `person` (`first_name`, `last_name`, `age`) values (?, ?, ?) * ``` * * @@ -176,15 +195,17 @@ export class InsertQueryBuilder * ```ts * import { sql } from 'kysely' * + * const ani = "Ani" + * const ston = "ston" + * * const result = await db * .insertInto('person') * .values(({ ref, selectFrom, fn }) => ({ * first_name: 'Jennifer', - * last_name: sql`${'Ani'} || ${'ston'}`, + * last_name: sql`>concat(${ani}, ${ston})`, * middle_name: ref('first_name'), * age: selectFrom('person') - * .select(fn.avg('age') - * .as('avg_age')), + * .select(fn.avg('age').as('avg_age')), * })) * .executeTakeFirst() * ``` @@ -192,8 +213,18 @@ export class InsertQueryBuilder * The generated SQL (PostgreSQL): * * ```sql - * insert into "person" ("first_name", "last_name", "age") - * values ($1, $2 || $3, (select avg("age") as "avg_age" from "person")) + * insert into "person" ( + * "first_name", + * "last_name", + * "middle_name", + * "age" + * ) + * values ( + * $1, + * concat($2, $3), + * "first_name", + * (select avg("age") as "avg_age" from "person") + * ) * ``` * * You can also use the callback version of subqueries or raw expressions: @@ -211,12 +242,6 @@ export class InsertQueryBuilder * })) * ``` */ - values(insert: InsertObjectOrList): InsertQueryBuilder - - values( - insert: InsertObjectOrListFactory - ): InsertQueryBuilder - values(insert: InsertExpression): InsertQueryBuilder { const [columns, values] = parseInsertExpression(insert) @@ -252,7 +277,7 @@ export class InsertQueryBuilder * ``` */ columns( - columns: ReadonlyArray + columns: ReadonlyArray, ): InsertQueryBuilder { return new InsertQueryBuilder({ ...this.#props, @@ -267,21 +292,35 @@ export class InsertQueryBuilder * * ### Examples * + * + * + * You can create an `INSERT INTO SELECT FROM` query using the `expression` method. + * This API doesn't follow our WYSIWYG principles and might be a bit difficult to + * remember. The reasons for this design stem from implementation difficulties. + * * ```ts - * db.insertInto('person') - * .columns(['first_name']) - * .expression((eb) => eb.selectFrom('pet').select('pet.name')) + * const result = await db.insertInto('person') + * .columns(['first_name', 'last_name', 'age']) + * .expression((eb) => eb + * .selectFrom('pet') + * .select((eb) => [ + * 'pet.name', + * eb.val('Petson').as('last_name'), + * eb.lit(7).as('age'), + * ]) + * ) + * .execute() * ``` * * The generated SQL (PostgreSQL): * * ```sql - * insert into "person" ("first_name") - * select "pet"."name" from "pet" + * insert into "person" ("first_name", "last_name", "age") + * select "pet"."name", $1 as "last_name", 7 as "age from "pet" * ``` */ expression( - expression: ExpressionOrFactory + expression: ExpressionOrFactory, ): InsertQueryBuilder { return new InsertQueryBuilder({ ...this.#props, @@ -291,6 +330,26 @@ export class InsertQueryBuilder }) } + /** + * Creates an `insert into "person" default values` query. + * + * ### Examples + * + * ```ts + * await db.insertInto('person') + * .defaultValues() + * .execute() + * ``` + */ + defaultValues(): InsertQueryBuilder { + return new InsertQueryBuilder({ + ...this.#props, + queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, { + defaultValues: true, + }), + }) + } + /** * Changes an `insert into` query to an `insert ignore into` query. * @@ -321,6 +380,62 @@ export class InsertQueryBuilder }) } + /** + * Changes an `insert into` query to an `insert top into` query. + * + * `top` clause is only supported by some dialects like MS SQL Server. + * + * ### Examples + * + * Insert the first 5 rows: + * + * ```ts + * await db.insertInto('person') + * .top(5) + * .columns(['first_name', 'gender']) + * .expression( + * (eb) => eb.selectFrom('pet').select(['name', sql.lit('other').as('gender')]) + * ) + * .execute() + * ``` + * + * The generated SQL (MS SQL Server): + * + * ```sql + * insert top(5) into "person" ("first_name", "gender") select "name", 'other' as "gender" from "pet" + * ``` + * + * Insert the first 50 percent of rows: + * + * ```ts + * await db.insertInto('person') + * .top(50, 'percent') + * .columns(['first_name', 'gender']) + * .expression( + * (eb) => eb.selectFrom('pet').select(['name', sql.lit('other').as('gender')]) + * ) + * .execute() + * ``` + * + * The generated SQL (MS SQL Server): + * + * ```sql + * insert top(50) percent into "person" ("first_name", "gender") select "name", 'other' as "gender" from "pet" + * ``` + */ + top( + expression: number | bigint, + modifiers?: 'percent', + ): InsertQueryBuilder { + return new InsertQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithTop( + this.#props.queryNode, + parseTop(expression, modifiers), + ), + }) + } + /** * Adds an `on conflict` clause to the query. * @@ -390,7 +505,7 @@ export class InsertQueryBuilder * species: 'cat', * }) * .onConflict((oc) => oc - * .expression(sql`lower(name)`) + * .expression(sql`lower(name)`) * .doUpdateSet({ species: 'hamster' }) * ) * .execute() @@ -474,8 +589,13 @@ export class InsertQueryBuilder */ onConflict( callback: ( - builder: OnConflictBuilder - ) => OnConflictDoNothingBuilder | OnConflictUpdateBuilder + builder: OnConflictBuilder, + ) => + | OnConflictUpdateBuilder< + OnConflictDatabase, + OnConflictTables + > + | OnConflictDoNothingBuilder, ): InsertQueryBuilder { return new InsertQueryBuilder({ ...this.#props, @@ -483,7 +603,7 @@ export class InsertQueryBuilder onConflict: callback( new OnConflictBuilder({ onConflictNode: OnConflictNode.create(), - }) + }), ).toOperationNode(), }), }) @@ -508,26 +628,38 @@ export class InsertQueryBuilder * ``` */ onDuplicateKeyUpdate( - update: UpdateExpression + update: UpdateObjectExpression, ): InsertQueryBuilder { return new InsertQueryBuilder({ ...this.#props, queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, { onDuplicateKey: OnDuplicateKeyNode.create( - parseUpdateExpression(update) + parseUpdateObjectExpression(update), ), }), }) } returning>( - selection: SelectArg + selections: ReadonlyArray, + ): InsertQueryBuilder> + + returning>( + callback: CB, + ): InsertQueryBuilder> + + returning>( + selection: SE, + ): InsertQueryBuilder> + + returning>( + selection: SelectArg, ): InsertQueryBuilder> { return new InsertQueryBuilder({ ...this.#props, queryNode: QueryNode.cloneWithReturning( this.#props.queryNode, - parseSelectArg(selection) + parseSelectArg(selection), ), }) } @@ -537,11 +669,82 @@ export class InsertQueryBuilder ...this.#props, queryNode: QueryNode.cloneWithReturning( this.#props.queryNode, - parseSelectAll() + parseSelectAll(), + ), + }) + } + + output>( + selections: readonly OE[] + ): InsertQueryBuilder< + DB, + TB, + ReturningRow> + > + + output>( + callback: CB + ): InsertQueryBuilder< + DB, + TB, + ReturningRow> + > + + output>( + selection: OE + ): InsertQueryBuilder< + DB, + TB, + ReturningRow> + > + + output(args: any): any { + return new InsertQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithOutput( + this.#props.queryNode, + parseSelectArg(args) ), }) } + outputAll( + table: 'inserted' + ): InsertQueryBuilder> { + return new InsertQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithOutput( + this.#props.queryNode, + parseSelectAll(table) + ), + }) + } + + /** + * Clears all `returning` clauses from the query. + * + * ### Examples + * + * ```ts + * db.insertInto('person') + * .values({ first_name: 'James', last_name: 'Smith', age: 42 }) + * .returning(['first_name']) + * .clearReturning() + * ``` + * + * The generated SQL(PostgreSQL): + * + * ```sql + * insert into "person" ("James", "Smith", 42) + * ``` + */ + clearReturning(): InsertQueryBuilder { + return new InsertQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithoutReturning(this.#props.queryNode), + }) + } + /** * Simply calls the provided function passing `this` as the only argument. `$call` returns * what the provided function returns. @@ -569,13 +772,6 @@ export class InsertQueryBuilder return func(this) } - /** - * @deprecated Use `$call` instead - */ - call(func: (qb: this) => T): T { - return this.$call(func) - } - /** * Call `func(this)` if `condition` is true. * @@ -613,27 +809,7 @@ export class InsertQueryBuilder */ $if( condition: boolean, - func: (qb: this) => InsertQueryBuilder - ): O2 extends InsertResult - ? InsertQueryBuilder - : O2 extends O & infer E - ? InsertQueryBuilder> - : InsertQueryBuilder> { - if (condition) { - return func(this) as any - } - - return new InsertQueryBuilder({ - ...this.#props, - }) as any - } - - /** - * @deprecated Use `$if` instead - */ - if( - condition: boolean, - func: (qb: this) => InsertQueryBuilder + func: (qb: this) => InsertQueryBuilder, ): O2 extends InsertResult ? InsertQueryBuilder : O2 extends O & infer E @@ -651,20 +827,13 @@ export class InsertQueryBuilder /** * Change the output type of the query. * - * You should only use this method as the last resort if the types - * don't support your use case. + * This method call doesn't change the SQL in any way. This methods simply + * returns a copy of this `InsertQueryBuilder` with a new output type. */ - $castTo(): InsertQueryBuilder { + $castTo(): InsertQueryBuilder { return new InsertQueryBuilder(this.#props) } - /** - * @deprecated Use `$castTo` instead. - */ - castTo(): InsertQueryBuilder { - return this.$castTo() - } - /** * Narrows (parts of) the output type of the query. * @@ -756,15 +925,6 @@ export class InsertQueryBuilder return new InsertQueryBuilder(this.#props) as unknown as any } - /** - * @deprecated Use `$assertType` instead. - */ - assertType(): O extends T - ? InsertQueryBuilder - : KyselyTypeError<`assertType() call failed: The type passed in is not equal to the output type of the query.`> { - return new InsertQueryBuilder(this.#props) as unknown as any - } - /** * Returns a copy of this InsertQueryBuilder instance with the given plugin installed. */ @@ -778,14 +938,14 @@ export class InsertQueryBuilder toOperationNode(): InsertQueryNode { return this.#props.executor.transformQuery( this.#props.queryNode, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -796,14 +956,19 @@ export class InsertQueryBuilder */ async execute(): Promise[]> { const compiledQuery = this.compile() - const query = compiledQuery.query as InsertQueryNode const result = await this.#props.executor.executeQuery( compiledQuery, - this.#props.queryId + this.#props.queryId, ) - if (this.#props.executor.adapter.supportsReturning && query.returning) { + const { adapter } = this.#props.executor + const query = compiledQuery.query as InsertQueryNode + + if ( + (query.returning && adapter.supportsReturning) || + (query.output && adapter.supportsOutput) + ) { return result.rows as any } @@ -811,7 +976,7 @@ export class InsertQueryBuilder new InsertResult( result.insertId, // TODO: remove numUpdatedOrDeletedRows. - result.numAffectedRows ?? result.numUpdatedOrDeletedRows + result.numAffectedRows ?? result.numUpdatedOrDeletedRows, ) as any, ] } @@ -836,7 +1001,7 @@ export class InsertQueryBuilder async executeTakeFirstOrThrow( errorConstructor: | NoResultErrorConstructor - | ((node: QueryNode) => Error) = NoResultError + | ((node: QueryNode) => Error) = NoResultError, ): Promise> { const result = await this.executeTakeFirst() @@ -857,7 +1022,7 @@ export class InsertQueryBuilder const stream = this.#props.executor.stream( compiledQuery, chunkSize, - this.#props.queryId + this.#props.queryId, ) for await (const item of stream) { @@ -867,14 +1032,14 @@ export class InsertQueryBuilder async explain = Record>( format?: ExplainFormat, - options?: Expression + options?: Expression, ): Promise { const builder = new InsertQueryBuilder({ ...this.#props, queryNode: QueryNode.cloneWithExplain( this.#props.queryNode, format, - options + options, ), }) @@ -884,7 +1049,7 @@ export class InsertQueryBuilder preventAwait( InsertQueryBuilder, - "don't await InsertQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`." + "don't await InsertQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`.", ) export interface InsertQueryBuilderProps { diff --git a/src/query-builder/insert-result.ts b/src/query-builder/insert-result.ts index 2fe9d9535..e5e8a10e1 100644 --- a/src/query-builder/insert-result.ts +++ b/src/query-builder/insert-result.ts @@ -23,7 +23,14 @@ */ export class InsertResult { /** - * The auto incrementing primary key + * 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 @@ -34,7 +41,7 @@ export class InsertResult { constructor( insertId: bigint | undefined, - numInsertedOrUpdatedRows: bigint | undefined + numInsertedOrUpdatedRows: bigint | undefined, ) { this.insertId = insertId this.numInsertedOrUpdatedRows = numInsertedOrUpdatedRows diff --git a/src/query-builder/join-builder.ts b/src/query-builder/join-builder.ts index 831f12abb..9866faa67 100644 --- a/src/query-builder/join-builder.ts +++ b/src/query-builder/join-builder.ts @@ -1,23 +1,17 @@ -import { Expression } from '../expression/expression.js' import { JoinNode } from '../operation-node/join-node.js' import { OperationNodeSource } from '../operation-node/operation-node-source.js' import { RawNode } from '../operation-node/raw-node.js' import { ComparisonOperatorExpression, OperandValueExpressionOrList, - parseOn, - parseReferentialComparison, + parseValueBinaryOperationOrExpression, + parseReferentialBinaryOperation, } from '../parser/binary-operation-parser.js' +import { ExpressionOrFactory } from '../parser/expression-parser.js' import { ReferenceExpression } from '../parser/reference-parser.js' -import { - ExistsExpression, - parseExists, - parseNotExists, -} from '../parser/unary-operation-parser.js' import { freeze } from '../util/object-utils.js' import { preventAwait } from '../util/prevent-await.js' import { SqlBool } from '../util/type-utils.js' -import { OnExpressionBuilder } from './deprecated-on-expression-builder.js' export class JoinBuilder implements OperationNodeSource @@ -37,45 +31,18 @@ export class JoinBuilder on>( lhs: RE, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: OperandValueExpressionOrList, ): JoinBuilder - on(factory: OnExpressionFactory): JoinBuilder - on(expression: Expression): JoinBuilder + on(expression: ExpressionOrFactory): JoinBuilder on(...args: any[]): JoinBuilder { return new JoinBuilder({ ...this.#props, - joinNode: JoinNode.cloneWithOn(this.#props.joinNode, parseOn(args)), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orOn>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): JoinBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orOn(factory: OnExpressionFactory): JoinBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orOn(expression: Expression): JoinBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orOn(...args: any[]): JoinBuilder { - return new JoinBuilder({ - ...this.#props, - joinNode: JoinNode.cloneWithOrOn(this.#props.joinNode, parseOn(args)), + joinNode: JoinNode.cloneWithOn( + this.#props.joinNode, + parseValueBinaryOperationOrExpression(args), + ), }) } @@ -88,73 +55,13 @@ export class JoinBuilder onRef( lhs: ReferenceExpression, op: ComparisonOperatorExpression, - rhs: ReferenceExpression + rhs: ReferenceExpression, ): JoinBuilder { return new JoinBuilder({ ...this.#props, joinNode: JoinNode.cloneWithOn( this.#props.joinNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orOnRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): JoinBuilder { - return new JoinBuilder({ - ...this.#props, - joinNode: JoinNode.cloneWithOrOn( - this.#props.joinNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - onExists(arg: ExistsExpression): JoinBuilder { - return new JoinBuilder({ - ...this.#props, - joinNode: JoinNode.cloneWithOn(this.#props.joinNode, parseExists(arg)), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - onNotExists(arg: ExistsExpression): JoinBuilder { - return new JoinBuilder({ - ...this.#props, - joinNode: JoinNode.cloneWithOn(this.#props.joinNode, parseNotExists(arg)), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orOnExists(arg: ExistsExpression): JoinBuilder { - return new JoinBuilder({ - ...this.#props, - joinNode: JoinNode.cloneWithOrOn(this.#props.joinNode, parseExists(arg)), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orOnNotExists(arg: ExistsExpression): JoinBuilder { - return new JoinBuilder({ - ...this.#props, - joinNode: JoinNode.cloneWithOrOn( - this.#props.joinNode, - parseNotExists(arg) + parseReferentialBinaryOperation(lhs, op, rhs), ), }) } @@ -167,7 +74,7 @@ export class JoinBuilder ...this.#props, joinNode: JoinNode.cloneWithOn( this.#props.joinNode, - RawNode.createWithSql('true') + RawNode.createWithSql('true'), ), }) } @@ -187,13 +94,9 @@ export class JoinBuilder preventAwait( JoinBuilder, - "don't await JoinBuilder instances. They are never executed directly and are always just a part of a query." + "don't await JoinBuilder instances. They are never executed directly and are always just a part of a query.", ) export interface JoinBuilderProps { readonly joinNode: JoinNode } - -type OnExpressionFactory = ( - eb: OnExpressionBuilder -) => Expression | OnExpressionBuilder diff --git a/src/query-builder/json-path-builder.ts b/src/query-builder/json-path-builder.ts new file mode 100644 index 000000000..a0eebf9a6 --- /dev/null +++ b/src/query-builder/json-path-builder.ts @@ -0,0 +1,294 @@ +import { + AliasableExpression, + AliasedExpression, + Expression, +} from '../expression/expression.js' +import { AliasNode } from '../operation-node/alias-node.js' +import { IdentifierNode } from '../operation-node/identifier-node.js' +import { JSONOperatorChainNode } from '../operation-node/json-operator-chain-node.js' +import { + JSONPathLegNode, + JSONPathLegType, +} from '../operation-node/json-path-leg-node.js' +import { JSONPathNode } from '../operation-node/json-path-node.js' +import { JSONReferenceNode } from '../operation-node/json-reference-node.js' +import { isOperationNodeSource } from '../operation-node/operation-node-source.js' +import { OperationNode } from '../operation-node/operation-node.js' +import { ValueNode } from '../operation-node/value-node.js' + +export class JSONPathBuilder { + readonly #node: JSONReferenceNode | JSONPathNode + + constructor(node: JSONReferenceNode | JSONPathNode) { + 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 + * db.selectFrom('person').select(eb => + * eb.ref('nicknames', '->').at(0).as('primary_nickname') + * ) + * + * 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[keyof NonNullable & number]>, + >( + index: `${I}` extends `${any}.${any}` | `#--${any}` ? never : I, + ): TraversedJSONPathBuilder { + 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< + K extends any[] extends O + ? never + : O extends object + ? keyof NonNullable & string + : never, + O2 = undefined extends O + ? null | NonNullable[K]> + : null extends O + ? null | NonNullable[K]> + : // when the object has non-specific keys, e.g. Record, should infer `T | null`! + string extends keyof NonNullable + ? null | NonNullable[K]> + : NonNullable[K], + >(key: K): TraversedJSONPathBuilder { + return this.#createBuilderWithPathLeg('Member', key) + } + + #createBuilderWithPathLeg( + legType: JSONPathLegType, + value: string | number, + ): TraversedJSONPathBuilder { + if (JSONReferenceNode.is(this.#node)) { + return new TraversedJSONPathBuilder( + JSONReferenceNode.cloneWithTraversal( + this.#node, + JSONPathNode.is(this.#node.traversal) + ? JSONPathNode.cloneWithLeg( + this.#node.traversal, + JSONPathLegNode.create(legType, value), + ) + : JSONOperatorChainNode.cloneWithValue( + this.#node.traversal, + ValueNode.createImmediate(value), + ), + ), + ) + } + + return new TraversedJSONPathBuilder( + JSONPathNode.cloneWithLeg( + this.#node, + JSONPathLegNode.create(legType, value), + ), + ) + } +} + +export class TraversedJSONPathBuilder + extends JSONPathBuilder + implements AliasableExpression +{ + readonly #node: JSONReferenceNode | JSONPathNode + + constructor(node: JSONReferenceNode | JSONPathNode) { + super(node) + this.#node = node + } + + /** @private */ + get expressionType(): O | undefined { + return 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): + * + * ```ts + * select "first_name" = $1 as "is_jennifer" + * from "person" + * ``` + */ + as(alias: A): AliasedExpression + as(alias: Expression): AliasedExpression + as(alias: string | Expression): AliasedExpression { + 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(): JSONPathBuilder { + return new JSONPathBuilder(this.#node) + } + + $notNull(): JSONPathBuilder> { + return new JSONPathBuilder(this.#node) + } + + toOperationNode(): OperationNode { + return this.#node + } +} + +export class AliasedJSONPathBuilder + implements AliasedExpression +{ + readonly #jsonPath: TraversedJSONPathBuilder + readonly #alias: A | Expression + + constructor( + jsonPath: TraversedJSONPathBuilder, + alias: A | Expression, + ) { + this.#jsonPath = jsonPath + this.#alias = alias + } + + /** @private */ + get expression(): Expression { + return this.#jsonPath + } + + /** @private */ + get alias(): A | Expression { + return this.#alias + } + + toOperationNode(): AliasNode { + return AliasNode.create( + this.#jsonPath.toOperationNode(), + isOperationNodeSource(this.#alias) + ? this.#alias.toOperationNode() + : IdentifierNode.create(this.#alias), + ) + } +} diff --git a/src/query-builder/merge-query-builder.ts b/src/query-builder/merge-query-builder.ts new file mode 100644 index 000000000..4792d234f --- /dev/null +++ b/src/query-builder/merge-query-builder.ts @@ -0,0 +1,1114 @@ +import { AliasedExpression } from '../expression/expression.js' +import { InsertQueryNode } from '../operation-node/insert-query-node.js' +import { MergeQueryNode } from '../operation-node/merge-query-node.js' +import { OperationNodeSource } from '../operation-node/operation-node-source.js' +import { QueryNode } from '../operation-node/query-node.js' +import { UpdateQueryNode } from '../operation-node/update-query-node.js' +import { + ComparisonOperatorExpression, + OperandValueExpressionOrList, +} from '../parser/binary-operation-parser.js' +import { ExpressionOrFactory } from '../parser/expression-parser.js' +import { + InsertExpression, + InsertObjectOrList, + InsertObjectOrListFactory, + parseInsertExpression, +} from '../parser/insert-values-parser.js' +import { + JoinCallbackExpression, + JoinReferenceExpression, + parseJoin, +} from '../parser/join-parser.js' +import { parseMergeThen, parseMergeWhen } from '../parser/merge-parser.js' +import { ReferenceExpression } from '../parser/reference-parser.js' +import { ReturningAllRow, ReturningRow } from '../parser/returning-parser.js' +import { parseSelectAll, parseSelectArg } from '../parser/select-parser.js' +import { TableExpression } from '../parser/table-parser.js' +import { parseTop } from '../parser/top-parser.js' +import { + ExtractUpdateTypeFromReferenceExpression, + UpdateObject, + UpdateObjectFactory, +} from '../parser/update-set-parser.js' +import { ValueExpression } from '../parser/value-parser.js' +import { CompiledQuery } from '../query-compiler/compiled-query.js' +import { NOOP_QUERY_EXECUTOR } from '../query-executor/noop-query-executor.js' +import { QueryExecutor } from '../query-executor/query-executor.js' +import { Compilable } from '../util/compilable.js' +import { freeze } from '../util/object-utils.js' +import { preventAwait } from '../util/prevent-await.js' +import { QueryId } from '../util/query-id.js' +import { + ShallowRecord, + SimplifyResult, + SimplifySingleResult, + SqlBool, +} from '../util/type-utils.js' +import { InsertQueryBuilder } from './insert-query-builder.js' +import { MergeResult } from './merge-result.js' +import { + NoResultError, + NoResultErrorConstructor, + isNoResultErrorConstructor, +} from './no-result-error.js' +import { + OutputCallback, + OutputExpression, + OutputInterface, + OutputPrefix, + SelectExpressionFromOutputCallback, + SelectExpressionFromOutputExpression, +} from './output-interface.js' +import { UpdateQueryBuilder } from './update-query-builder.js' + +export class MergeQueryBuilder + implements OutputInterface +{ + readonly #props: MergeQueryBuilderProps + + constructor(props: MergeQueryBuilderProps) { + this.#props = freeze(props) + } + + /** + * 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: number | bigint, + modifiers?: 'percent', + ): MergeQueryBuilder { + return new MergeQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithTop( + this.#props.queryNode, + parseTop(expression, modifiers), + ), + }) + } + + /** + * Adds the `using` clause to the query. + * + * This method is similar to {@link SelectQueryBuilder.innerJoin}, so see the + * documentation for that method for more examples. + * + * ### 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 + * ``` + */ + using< + TE extends TableExpression, + K1 extends JoinReferenceExpression, + K2 extends JoinReferenceExpression, + >( + sourceTable: TE, + k1: K1, + k2: K2, + ): ExtractWheneableMergeQueryBuilder + + using< + TE extends TableExpression, + FN extends JoinCallbackExpression, + >( + sourceTable: TE, + callback: FN, + ): ExtractWheneableMergeQueryBuilder + + using(...args: any): any { + return new WheneableMergeQueryBuilder({ + ...this.#props, + queryNode: MergeQueryNode.cloneWithUsing( + this.#props.queryNode, + parseJoin('Using', args), + ), + }) + } + + output>( + selections: readonly OE[], + ): MergeQueryBuilder< + DB, + TT, + ReturningRow> + > + + output>( + callback: CB, + ): MergeQueryBuilder< + DB, + TT, + ReturningRow> + > + + output>( + selection: OE, + ): MergeQueryBuilder< + DB, + TT, + ReturningRow> + > + + output(args: any): any { + return new MergeQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithOutput( + this.#props.queryNode, + parseSelectArg(args), + ), + }) + } + + outputAll( + table: OutputPrefix, + ): MergeQueryBuilder> { + return new MergeQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithOutput( + this.#props.queryNode, + parseSelectAll(table), + ), + }) + } +} + +preventAwait( + MergeQueryBuilder, + "don't await MergeQueryBuilder instances directly. To execute the query you need to call `execute` when available.", +) + +export interface MergeQueryBuilderProps { + readonly queryId: QueryId + readonly queryNode: MergeQueryNode + readonly executor: QueryExecutor +} + +export class WheneableMergeQueryBuilder< + DB, + TT extends keyof DB, + ST extends keyof DB, + O, + > + implements Compilable, OutputInterface, OperationNodeSource +{ + readonly #props: MergeQueryBuilderProps + + constructor(props: MergeQueryBuilderProps) { + this.#props = freeze(props) + } + + /** + * See {@link MergeQueryBuilder.top}. + */ + top( + expression: number | bigint, + modifiers?: 'percent', + ): WheneableMergeQueryBuilder { + return new WheneableMergeQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithTop( + this.#props.queryNode, + 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(): MatchedThenableMergeQueryBuilder { + return this.#whenMatched([]) + } + + /** + * Adds the `when matched` clause to the query with an `and` condition. + * + * This method is similar to {@link SelectQueryBuilder.where}, so see the documentation + * for that method for more examples. + * + * For a simple `when matched` clause (without an `and` condition) see {@link whenMatched}. + * + * ### Examples + * + * ```ts + * const result = await db.mergeInto('person') + * .using('pet', 'person.id', 'pet.owner_id') + * .whenMatchedAnd('person.first_name', '=', 'John') + * .thenDelete() + * .execute() + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * merge into "person" + * using "pet" on "person"."id" = "pet"."owner_id" + * when matched and "person"."first_name" = $1 then + * delete + * ``` + */ + whenMatchedAnd< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( + lhs: RE, + op: ComparisonOperatorExpression, + rhs: VE, + ): MatchedThenableMergeQueryBuilder + + whenMatchedAnd>( + expression: E, + ): MatchedThenableMergeQueryBuilder + + whenMatchedAnd( + ...args: any[] + ): MatchedThenableMergeQueryBuilder { + 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< + LRE extends ReferenceExpression, + RRE extends ReferenceExpression, + >( + lhs: LRE, + op: ComparisonOperatorExpression, + rhs: RRE, + ): MatchedThenableMergeQueryBuilder { + return this.#whenMatched([lhs, op, rhs], true) + } + + #whenMatched( + args: any[], + refRight?: boolean, + ): MatchedThenableMergeQueryBuilder { + return new MatchedThenableMergeQueryBuilder({ + ...this.#props, + queryNode: MergeQueryNode.cloneWithWhen( + this.#props.queryNode, + 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(): NotMatchedThenableMergeQueryBuilder { + return this.#whenNotMatched([]) + } + + /** + * Adds the `when not matched` clause to the query with an `and` condition. + * + * This method is similar to {@link SelectQueryBuilder.where}, so see the documentation + * for that method for more examples. + * + * For a simple `when not matched` clause (without an `and` condition) see {@link whenNotMatched}. + * + * Unlike {@link whenMatchedAnd}, you cannot reference columns from the table merged into. + * + * ### Examples + * + * ```ts + * const result = await db.mergeInto('person') + * .using('pet', 'person.id', 'pet.owner_id') + * .whenNotMatchedAnd('pet.name', '=', 'Lucky') + * .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 and "pet"."name" = $1 then + * insert ("first_name", "last_name") values ($2, $3) + * ``` + */ + whenNotMatchedAnd< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( + lhs: RE, + op: ComparisonOperatorExpression, + rhs: VE, + ): NotMatchedThenableMergeQueryBuilder + + whenNotMatchedAnd>( + expression: E, + ): NotMatchedThenableMergeQueryBuilder + + whenNotMatchedAnd( + ...args: any[] + ): NotMatchedThenableMergeQueryBuilder { + 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< + LRE extends ReferenceExpression, + RRE extends ReferenceExpression, + >( + lhs: LRE, + op: ComparisonOperatorExpression, + rhs: RRE, + ): NotMatchedThenableMergeQueryBuilder { + 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(): MatchedThenableMergeQueryBuilder< + DB, + TT, + ST, + TT, + O + > { + return this.#whenNotMatched([], false, true) + } + + /** + * Adds the `when not matched by source` clause to the query with an `and` condition. + * + * Supported in MS SQL Server. + * + * Similar to {@link whenNotMatchedAnd}, but returns a {@link MatchedThenableMergeQueryBuilder}. + */ + whenNotMatchedBySourceAnd< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( + lhs: RE, + op: ComparisonOperatorExpression, + rhs: VE, + ): MatchedThenableMergeQueryBuilder + + whenNotMatchedBySourceAnd>( + expression: E, + ): MatchedThenableMergeQueryBuilder + + whenNotMatchedBySourceAnd( + ...args: any[] + ): MatchedThenableMergeQueryBuilder { + 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< + LRE extends ReferenceExpression, + RRE extends ReferenceExpression, + >( + lhs: LRE, + op: ComparisonOperatorExpression, + rhs: RRE, + ): MatchedThenableMergeQueryBuilder { + return this.#whenNotMatched([lhs, op, rhs], true, true) + } + + output>( + selections: readonly OE[], + ): WheneableMergeQueryBuilder< + DB, + TT, + ST, + ReturningRow> + > + + output>( + callback: CB, + ): WheneableMergeQueryBuilder< + DB, + TT, + ST, + ReturningRow> + > + + output>( + selection: OE, + ): WheneableMergeQueryBuilder< + DB, + TT, + ST, + ReturningRow> + > + + output(args: any): any { + return new WheneableMergeQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithOutput( + this.#props.queryNode, + parseSelectArg(args), + ), + }) + } + + outputAll( + table: OutputPrefix, + ): WheneableMergeQueryBuilder> { + return new WheneableMergeQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithOutput( + this.#props.queryNode, + parseSelectAll(table), + ), + }) + } + + #whenNotMatched( + args: any[], + refRight: boolean = false, + bySource: boolean = false, + ): any { + const props: MergeQueryBuilderProps = { + ...this.#props, + queryNode: MergeQueryNode.cloneWithWhen( + this.#props.queryNode, + parseMergeWhen({ isMatched: false, bySource }, args, refRight), + ), + } + + const Builder: any = 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 + * function log(qb: T): T { + * console.log(qb.compile()) + * return qb + * } + * + * db.updateTable('person') + * .set(values) + * .$call(log) + * .execute() + * ``` + */ + $call(func: (qb: this) => T): T { + 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 updatePerson(id: number, updates: UpdateablePerson, 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 + * { + * id: number + * first_name: string + * last_name?: string + * } + * ``` + */ + $if( + condition: boolean, + func: (qb: this) => WheneableMergeQueryBuilder, + ): O2 extends MergeResult + ? WheneableMergeQueryBuilder + : O2 extends O & infer E + ? WheneableMergeQueryBuilder> + : WheneableMergeQueryBuilder> { + if (condition) { + return func(this) as any + } + + return new WheneableMergeQueryBuilder({ + ...this.#props, + }) as any + } + + toOperationNode(): MergeQueryNode { + return this.#props.executor.transformQuery( + this.#props.queryNode, + this.#props.queryId, + ) + } + + compile(): CompiledQuery { + 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(): Promise[]> { + const compiledQuery = this.compile() + + const result = await this.#props.executor.executeQuery( + compiledQuery, + this.#props.queryId, + ) + + if ( + (compiledQuery.query as MergeQueryNode).output && + this.#props.executor.adapter.supportsOutput + ) { + return result.rows as any + } + + return [new MergeResult(result.numAffectedRows) as any] + } + + /** + * Executes the query and returns the first result or undefined if + * the query returned no result. + */ + async executeTakeFirst(): Promise> { + const [result] = await this.execute() + return result as SimplifySingleResult + } + + /** + * 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: + | NoResultErrorConstructor + | ((node: QueryNode) => Error) = NoResultError, + ): Promise> { + const result = await this.executeTakeFirst() + + if (result === undefined) { + const error = isNoResultErrorConstructor(errorConstructor) + ? new errorConstructor(this.toOperationNode()) + : errorConstructor(this.toOperationNode()) + + throw error + } + + return result as SimplifyResult + } +} + +preventAwait( + WheneableMergeQueryBuilder, + "don't await WheneableMergeQueryBuilder instances directly. To execute the query you need to call `execute`.", +) + +export class MatchedThenableMergeQueryBuilder< + DB, + TT extends keyof DB, + ST extends keyof DB, + UT extends TT | ST, + O, +> { + readonly #props: MergeQueryBuilderProps + + constructor(props: MergeQueryBuilderProps) { + this.#props = 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(): WheneableMergeQueryBuilder { + return new WheneableMergeQueryBuilder({ + ...this.#props, + queryNode: MergeQueryNode.cloneWithThen( + this.#props.queryNode, + 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(): WheneableMergeQueryBuilder { + return new WheneableMergeQueryBuilder({ + ...this.#props, + queryNode: MergeQueryNode.cloneWithThen( + this.#props.queryNode, + 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: Date.now(), + * }) + * ) + * .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: (ub: QB) => QB, + ): WheneableMergeQueryBuilder { + return new WheneableMergeQueryBuilder({ + ...this.#props, + queryNode: MergeQueryNode.cloneWithThen( + this.#props.queryNode, + parseMergeThen( + set( + new UpdateQueryBuilder({ + queryId: this.#props.queryId, + executor: NOOP_QUERY_EXECUTOR, + queryNode: UpdateQueryNode.createWithoutTable(), + }) as QB, + ), + ), + ), + }) + } + + /** + * Performs an `update set` action, similar to {@link UpdateQueryBuilder.set}. + * + * For a full-fledged update query builder, see {@link thenUpdate}. + * + * To perform the `delete` action, see {@link thenDelete}. + * + * To perform the `do nothing` action, see {@link thenDoNothing}. + * + * ### Examples + * + * ```ts + * const result = await db.mergeInto('person') + * .using('pet', 'person.id', 'pet.owner_id') + * .whenMatched() + * .thenUpdateSet({ + * middle_name: 'dog owner', + * }) + * .execute() + * ``` + * + * The generate SQL (PostgreSQL): + * + * ```sql + * merge into "person" + * using "pet" on "person"."id" = "pet"."owner_id" + * when matched then + * update set "middle_name" = $1 + * ``` + */ + thenUpdateSet>( + update: UO, + ): WheneableMergeQueryBuilder + + thenUpdateSet>( + update: U, + ): WheneableMergeQueryBuilder + + thenUpdateSet< + RE extends ReferenceExpression, + VE extends ValueExpression< + DB, + UT, + ExtractUpdateTypeFromReferenceExpression + >, + >(key: RE, value: VE): WheneableMergeQueryBuilder + + thenUpdateSet(...args: any[]): any { + // @ts-ignore not sure how to type this so it won't complain about set(...args). + return this.thenUpdate((ub) => ub.set(...args)) + } +} + +preventAwait( + MatchedThenableMergeQueryBuilder, + "don't await MatchedThenableMergeQueryBuilder instances directly. To execute the query you need to call `execute` when available.", +) + +export class NotMatchedThenableMergeQueryBuilder< + DB, + TT extends keyof DB, + ST extends keyof DB, + O, +> { + readonly #props: MergeQueryBuilderProps + + constructor(props: MergeQueryBuilderProps) { + this.#props = 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(): WheneableMergeQueryBuilder { + return new WheneableMergeQueryBuilder({ + ...this.#props, + queryNode: MergeQueryNode.cloneWithThen( + this.#props.queryNode, + parseMergeThen('do nothing'), + ), + }) + } + + /** + * Performs the `insert (...) values` action. + * + * This method is similar to {@link InsertQueryBuilder.values}, so see the documentation + * for that method for more examples. + * + * To perform the `do nothing` action, see {@link thenDoNothing}. + * + * ### 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) + * ``` + */ + thenInsertValues>( + insert: I, + ): WheneableMergeQueryBuilder + + thenInsertValues>( + insert: IO, + ): WheneableMergeQueryBuilder + + thenInsertValues>( + insert: IE, + ): WheneableMergeQueryBuilder { + const [columns, values] = parseInsertExpression(insert) + + return new WheneableMergeQueryBuilder({ + ...this.#props, + queryNode: MergeQueryNode.cloneWithThen( + this.#props.queryNode, + parseMergeThen( + InsertQueryNode.cloneWith(InsertQueryNode.createWithoutInto(), { + columns, + values, + }), + ), + ), + }) + } +} + +preventAwait( + NotMatchedThenableMergeQueryBuilder, + "don't await NotMatchedThenableMergeQueryBuilder instances directly. To execute the query you need to call `execute` when available.", +) + +export type ExtractWheneableMergeQueryBuilder< + DB, + TT extends keyof DB, + TE extends TableExpression, + O, +> = TE extends `${infer T} as ${infer A}` + ? T extends keyof DB + ? UsingBuilder + : never + : TE extends keyof DB + ? WheneableMergeQueryBuilder + : TE extends AliasedExpression + ? UsingBuilder + : TE extends (qb: any) => AliasedExpression + ? UsingBuilder + : never + +type UsingBuilder< + DB, + TT extends keyof DB, + A extends string, + R, + O, +> = A extends keyof DB + ? WheneableMergeQueryBuilder + : WheneableMergeQueryBuilder, TT, A, O> diff --git a/src/query-builder/merge-result.ts b/src/query-builder/merge-result.ts new file mode 100644 index 000000000..8425e0ed4 --- /dev/null +++ b/src/query-builder/merge-result.ts @@ -0,0 +1,7 @@ +export class MergeResult { + readonly numChangedRows: bigint | undefined + + constructor(numChangedRows: bigint | undefined) { + this.numChangedRows = numChangedRows + } +} diff --git a/src/query-builder/no-result-error.ts b/src/query-builder/no-result-error.ts index d3325647a..32bf7152d 100644 --- a/src/query-builder/no-result-error.ts +++ b/src/query-builder/no-result-error.ts @@ -15,7 +15,7 @@ export class NoResultError extends Error { } export function isNoResultErrorConstructor( - fn: NoResultErrorConstructor | ((node: QueryNode) => Error) + fn: NoResultErrorConstructor | ((node: QueryNode) => Error), ): fn is NoResultErrorConstructor { return Object.prototype.hasOwnProperty.call(fn, 'prototype') } diff --git a/src/query-builder/on-conflict-builder.ts b/src/query-builder/on-conflict-builder.ts index 9e1c80f0b..cfdfaeda8 100644 --- a/src/query-builder/on-conflict-builder.ts +++ b/src/query-builder/on-conflict-builder.ts @@ -6,23 +6,20 @@ import { OperationNodeSource } from '../operation-node/operation-node-source.js' import { ComparisonOperatorExpression, OperandValueExpressionOrList, - parseReferentialComparison, - parseWhere, + parseValueBinaryOperationOrExpression, + parseReferentialBinaryOperation, } from '../parser/binary-operation-parser.js' import { ExpressionOrFactory } from '../parser/expression-parser.js' import { ReferenceExpression } from '../parser/reference-parser.js' import { - parseExists, - parseNotExists, -} from '../parser/unary-operation-parser.js' -import { - UpdateExpression, - parseUpdateExpression, + UpdateObjectExpression, + parseUpdateObjectExpression, } from '../parser/update-set-parser.js' +import { Updateable } from '../util/column-type.js' import { freeze } from '../util/object-utils.js' import { preventAwait } from '../util/prevent-await.js' -import { AnyColumn } from '../util/type-utils.js' -import { WhereExpressionFactory, WhereInterface } from './where-interface.js' +import { AnyColumn, SqlBool } from '../util/type-utils.js' +import { WhereInterface } from './where-interface.js' export class OnConflictBuilder implements WhereInterface @@ -59,7 +56,7 @@ export class OnConflictBuilder * methods for alternative ways to specify the conflict target. */ columns( - columns: ReadonlyArray> + columns: ReadonlyArray>, ): OnConflictBuilder { const columnNodes = columns.map(ColumnNode.create) @@ -105,154 +102,42 @@ export class OnConflictBuilder }) } - /** - * Specify an index predicate for the index target. - * - * See {@link WhereInterface.where} for more info. - */ - where>( + where< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( lhs: RE, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: VE, ): OnConflictBuilder - where(factory: WhereExpressionFactory): OnConflictBuilder - where(expression: Expression): OnConflictBuilder + where>( + expression: E, + ): OnConflictBuilder where(...args: any[]): OnConflictBuilder { return new OnConflictBuilder({ ...this.#props, onConflictNode: OnConflictNode.cloneWithIndexWhere( this.#props.onConflictNode, - parseWhere(args) + parseValueBinaryOperationOrExpression(args), ), }) } - /** - * Specify an index predicate for the index target. - * - * See {@link WhereInterface.whereRef} for more info. - */ - whereRef( - lhs: ReferenceExpression, + whereRef< + LRE extends ReferenceExpression, + RRE extends ReferenceExpression, + >( + lhs: LRE, op: ComparisonOperatorExpression, - rhs: ReferenceExpression + rhs: RRE, ): OnConflictBuilder { return new OnConflictBuilder({ ...this.#props, onConflictNode: OnConflictNode.cloneWithIndexWhere( this.#props.onConflictNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): OnConflictBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere(factory: WhereExpressionFactory): OnConflictBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere(expression: Expression): OnConflictBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere(...args: any[]): OnConflictBuilder { - return new OnConflictBuilder({ - ...this.#props, - onConflictNode: OnConflictNode.cloneWithIndexOrWhere( - this.#props.onConflictNode, - parseWhere(args) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhereRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): OnConflictBuilder { - return new OnConflictBuilder({ - ...this.#props, - onConflictNode: OnConflictNode.cloneWithIndexOrWhere( - this.#props.onConflictNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - whereExists( - arg: ExpressionOrFactory - ): OnConflictBuilder { - return new OnConflictBuilder({ - ...this.#props, - onConflictNode: OnConflictNode.cloneWithIndexWhere( - this.#props.onConflictNode, - parseExists(arg) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - whereNotExists( - arg: ExpressionOrFactory - ): OnConflictBuilder { - return new OnConflictBuilder({ - ...this.#props, - onConflictNode: OnConflictNode.cloneWithIndexWhere( - this.#props.onConflictNode, - parseNotExists(arg) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhereExists( - arg: ExpressionOrFactory - ): OnConflictBuilder { - return new OnConflictBuilder({ - ...this.#props, - onConflictNode: OnConflictNode.cloneWithIndexOrWhere( - this.#props.onConflictNode, - parseExists(arg) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhereNotExists( - arg: ExpressionOrFactory - ): OnConflictBuilder { - return new OnConflictBuilder({ - ...this.#props, - onConflictNode: OnConflictNode.cloneWithIndexOrWhere( - this.#props.onConflictNode, - parseNotExists(arg) + parseReferentialBinaryOperation(lhs, op, rhs), ), }) } @@ -261,7 +146,7 @@ export class OnConflictBuilder return new OnConflictBuilder({ ...this.#props, onConflictNode: OnConflictNode.cloneWithoutIndexWhere( - this.#props.onConflictNode + this.#props.onConflictNode, ), }) } @@ -339,16 +224,16 @@ export class OnConflictBuilder * ``` */ doUpdateSet( - update: UpdateExpression< + update: UpdateObjectExpression< OnConflictDatabase, OnConflictTables, OnConflictTables - > + >, ): OnConflictUpdateBuilder, OnConflictTables> { return new OnConflictUpdateBuilder({ ...this.#props, onConflictNode: OnConflictNode.cloneWith(this.#props.onConflictNode, { - updates: parseUpdateExpression(update), + updates: parseUpdateObjectExpression(update), }), }) } @@ -369,7 +254,7 @@ export interface OnConflictBuilderProps { preventAwait(OnConflictBuilder, "don't await OnConflictBuilder instances.") export type OnConflictDatabase = { - [K in keyof DB | 'excluded']: K extends keyof DB ? DB[K] : DB[TB] + [K in keyof DB | 'excluded']: Updateable } export type OnConflictTables = TB | 'excluded' @@ -390,7 +275,7 @@ export class OnConflictDoNothingBuilder preventAwait( OnConflictDoNothingBuilder, - "don't await OnConflictDoNothingBuilder instances." + "don't await OnConflictDoNothingBuilder instances.", ) export class OnConflictUpdateBuilder @@ -407,24 +292,25 @@ export class OnConflictUpdateBuilder * * See {@link WhereInterface.where} for more info. */ - where>( + where< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( lhs: RE, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: VE, ): OnConflictUpdateBuilder - where( - factory: WhereExpressionFactory + where>( + expression: E, ): OnConflictUpdateBuilder - where(expression: Expression): OnConflictUpdateBuilder - where(...args: any[]): OnConflictUpdateBuilder { return new OnConflictUpdateBuilder({ ...this.#props, onConflictNode: OnConflictNode.cloneWithUpdateWhere( this.#props.onConflictNode, - parseWhere(args) + parseValueBinaryOperationOrExpression(args), ), }) } @@ -434,127 +320,19 @@ export class OnConflictUpdateBuilder * * See {@link WhereInterface.whereRef} for more info. */ - whereRef( - lhs: ReferenceExpression, + whereRef< + LRE extends ReferenceExpression, + RRE extends ReferenceExpression, + >( + lhs: LRE, op: ComparisonOperatorExpression, - rhs: ReferenceExpression + rhs: RRE, ): OnConflictUpdateBuilder { return new OnConflictUpdateBuilder({ ...this.#props, onConflictNode: OnConflictNode.cloneWithUpdateWhere( this.#props.onConflictNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): OnConflictUpdateBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere( - factory: WhereExpressionFactory - ): OnConflictUpdateBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere(expression: Expression): OnConflictUpdateBuilder - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere(...args: any[]): OnConflictUpdateBuilder { - return new OnConflictUpdateBuilder({ - ...this.#props, - onConflictNode: OnConflictNode.cloneWithUpdateOrWhere( - this.#props.onConflictNode, - parseWhere(args) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhereRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): OnConflictUpdateBuilder { - return new OnConflictUpdateBuilder({ - ...this.#props, - onConflictNode: OnConflictNode.cloneWithUpdateOrWhere( - this.#props.onConflictNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - whereExists( - arg: ExpressionOrFactory - ): OnConflictUpdateBuilder { - return new OnConflictUpdateBuilder({ - ...this.#props, - onConflictNode: OnConflictNode.cloneWithUpdateWhere( - this.#props.onConflictNode, - parseExists(arg) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - whereNotExists( - arg: ExpressionOrFactory - ): OnConflictUpdateBuilder { - return new OnConflictUpdateBuilder({ - ...this.#props, - onConflictNode: OnConflictNode.cloneWithUpdateWhere( - this.#props.onConflictNode, - parseNotExists(arg) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhereExists( - arg: ExpressionOrFactory - ): OnConflictUpdateBuilder { - return new OnConflictUpdateBuilder({ - ...this.#props, - onConflictNode: OnConflictNode.cloneWithUpdateOrWhere( - this.#props.onConflictNode, - parseExists(arg) - ), - }) - } - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhereNotExists( - arg: ExpressionOrFactory - ): OnConflictUpdateBuilder { - return new OnConflictUpdateBuilder({ - ...this.#props, - onConflictNode: OnConflictNode.cloneWithUpdateOrWhere( - this.#props.onConflictNode, - parseNotExists(arg) + parseReferentialBinaryOperation(lhs, op, rhs), ), }) } @@ -563,7 +341,7 @@ export class OnConflictUpdateBuilder return new OnConflictUpdateBuilder({ ...this.#props, onConflictNode: OnConflictNode.cloneWithoutUpdateWhere( - this.#props.onConflictNode + this.#props.onConflictNode, ), }) } @@ -583,5 +361,5 @@ export class OnConflictUpdateBuilder preventAwait( OnConflictUpdateBuilder, - "don't await OnConflictUpdateBuilder instances." + "don't await OnConflictUpdateBuilder instances.", ) diff --git a/src/query-builder/output-interface.ts b/src/query-builder/output-interface.ts new file mode 100644 index 000000000..8a44502fe --- /dev/null +++ b/src/query-builder/output-interface.ts @@ -0,0 +1,158 @@ +import { ExpressionBuilder } from '../expression/expression-builder.js' +import { AliasedExpressionOrFactory } from '../parser/expression-parser.js' +import { ReturningAllRow, ReturningRow } from '../parser/returning-parser.js' +import { + 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' + * }) + * .executeTakeFirst() + * ``` + * + * Return multiple columns: + * + * ```ts + * const { id, first_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()) + * .executeTakeFirst() + * ``` + * + * Return arbitrary expressions: + * + * ```ts + * import { sql } from 'kysely' + * + * const { id, full_name } = await db + * .deleteFrom('person') + * .output((eb) => sql`concat(${eb.ref('deleted.first_name')}, ' ', ${eb.ref('deleted.last_name')})`.as('full_name') + * .where('created_at', '<', new Date()) + * .executeTakeFirst() + * ``` + * + * 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', + * ]) + * ``` + */ + output>( + selections: ReadonlyArray, + ): OutputInterface< + DB, + TB, + ReturningRow>, + OP + > + + output>( + callback: CB, + ): OutputInterface< + DB, + TB, + ReturningRow>, + OP + > + + output>( + selection: OE, + ): OutputInterface< + DB, + TB, + ReturningRow>, + 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, 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, + OTB extends keyof ODB = keyof ODB, +> = + | AnyAliasedColumnWithTable + | AnyColumnWithTable + | AliasedExpressionOrFactory + +export type OutputCallback< + DB, + TB extends keyof DB, + OP extends OutputPrefix = OutputPrefix, +> = ( + eb: ExpressionBuilder, OP>, +) => ReadonlyArray> + +export type SelectExpressionFromOutputExpression = + OE extends `${OutputPrefix}.${infer C}` ? C : OE + +export type SelectExpressionFromOutputCallback = CB extends ( + eb: ExpressionBuilder, +) => ReadonlyArray + ? SelectExpressionFromOutputExpression + : never diff --git a/src/query-builder/over-builder.ts b/src/query-builder/over-builder.ts index 91ada55d2..330be843a 100644 --- a/src/query-builder/over-builder.ts +++ b/src/query-builder/over-builder.ts @@ -30,7 +30,7 @@ export class OverBuilder * const result = await db * .selectFrom('person') * .select( - * eb => eb.fn.avg('age').over( + * (eb) => eb.fn.avg('age').over( * ob => ob.orderBy('first_name', 'asc').orderBy('last_name', 'asc') * ).as('average_age') * ) @@ -44,14 +44,14 @@ export class OverBuilder * from "person" * ``` */ - orderBy( - orderBy: StringReference | DynamicReferenceBuilder, - direction?: OrderByDirectionExpression + orderBy | DynamicReferenceBuilder>( + orderBy: OE, + direction?: OrderByDirectionExpression, ): OverBuilder { return new OverBuilder({ - overNode: OverNode.cloneWithOrderByItem( + overNode: OverNode.cloneWithOrderByItems( this.#props.overNode, - parseOrderBy(orderBy, direction) + parseOrderBy([orderBy, direction]), ), }) } @@ -63,7 +63,7 @@ export class OverBuilder * const result = await db * .selectFrom('person') * .select( - * eb => eb.fn.avg('age').over( + * (eb) => eb.fn.avg('age').over( * ob => ob.partitionBy(['last_name', 'first_name']) * ).as('average_age') * ) @@ -78,16 +78,18 @@ export class OverBuilder * ``` */ partitionBy( - partitionBy: ReadonlyArray> + partitionBy: ReadonlyArray>, ): OverBuilder - partitionBy(partitionBy: PartitionByExpression): OverBuilder + partitionBy>( + partitionBy: PE, + ): OverBuilder partitionBy(partitionBy: PartitionByExpressionOrList): any { return new OverBuilder({ overNode: OverNode.cloneWithPartitionByItems( this.#props.overNode, - parsePartitionBy(partitionBy) + parsePartitionBy(partitionBy), ), }) } @@ -107,7 +109,7 @@ export class OverBuilder preventAwait( OverBuilder, - "don't await OverBuilder instances. They are never executed directly and are always just a part of a query." + "don't await OverBuilder instances. They are never executed directly and are always just a part of a query.", ) export interface OverBuilderProps { diff --git a/src/query-builder/returning-interface.ts b/src/query-builder/returning-interface.ts index 8ba78fce8..b89cc6bbe 100644 --- a/src/query-builder/returning-interface.ts +++ b/src/query-builder/returning-interface.ts @@ -1,5 +1,8 @@ -import { ReturningRow } from '../parser/returning-parser.js' -import { SelectExpression } from '../parser/select-parser.js' +import { + ReturningCallbackRow, + ReturningRow, +} from '../parser/returning-parser.js' +import { SelectCallback, SelectExpression } from '../parser/select-parser.js' import { Selectable } from '../util/column-type.js' export interface ReturningInterface { @@ -54,7 +57,7 @@ export interface ReturningInterface { * first_name: 'Jennifer', * last_name: 'Aniston' * }) - * .returning(eb => [ + * .returning((eb) => [ * 'id as id', * sql`concat(first_name, ' ', last_name)`.as('full_name'), * eb.selectFrom('pets').select('pet.id').limit(1).as('first_pet_id') @@ -63,16 +66,22 @@ export interface ReturningInterface { * ``` */ returning>( - selections: ReadonlyArray + selections: ReadonlyArray, ): ReturningInterface> + returning>( + callback: CB, + ): ReturningInterface> + returning>( - selection: SE + selection: SE, ): ReturningInterface> /** * Adds a `returning *` to an insert/update/delete query on databases * that support `returning` such as PostgreSQL. + * + * Also see the {@link returning} method. */ returningAll(): ReturningInterface> } diff --git a/src/query-builder/select-query-builder-expression.ts b/src/query-builder/select-query-builder-expression.ts new file mode 100644 index 000000000..2266bfa3d --- /dev/null +++ b/src/query-builder/select-query-builder-expression.ts @@ -0,0 +1,8 @@ +import { AliasableExpression } from '../expression/expression.js' +import { SelectQueryNode } from '../operation-node/select-query-node.js' + +export interface SelectQueryBuilderExpression + extends AliasableExpression { + get isSelectQueryBuilder(): true + toOperationNode(): SelectQueryNode +} diff --git a/src/query-builder/select-query-builder.ts b/src/query-builder/select-query-builder.ts index dd07b4772..2369c3071 100644 --- a/src/query-builder/select-query-builder.ts +++ b/src/query-builder/select-query-builder.ts @@ -6,7 +6,7 @@ import { JoinReferenceExpression, parseJoin, } from '../parser/join-parser.js' -import { TableExpression } from '../parser/table-parser.js' +import { TableExpression, parseTable } from '../parser/table-parser.js' import { parseSelectArg, parseSelectAll, @@ -14,6 +14,8 @@ import { Selection, SelectArg, AllSelection, + SelectCallback, + CallbackSelection, } from '../parser/select-parser.js' import { parseReferenceExpressionOrList, @@ -29,10 +31,13 @@ import { ShallowRecord, Simplify, SimplifySingleResult, + SqlBool, } from '../util/type-utils.js' import { OrderByDirectionExpression, OrderByExpression, + DirectedOrderByStringReference, + UndirectedOrderByExpression, parseOrderBy, } from '../parser/order-by-parser.js' import { preventAwait } from '../util/prevent-await.js' @@ -41,296 +46,94 @@ import { OffsetNode } from '../operation-node/offset-node.js' import { Compilable } from '../util/compilable.js' import { QueryExecutor } from '../query-executor/query-executor.js' import { QueryId } from '../util/query-id.js' -import { freeze } from '../util/object-utils.js' +import { asArray, freeze } from '../util/object-utils.js' import { GroupByArg, parseGroupBy } from '../parser/group-by-parser.js' import { KyselyPlugin } from '../plugin/kysely-plugin.js' -import { WhereExpressionFactory, WhereInterface } from './where-interface.js' +import { WhereInterface } from './where-interface.js' import { isNoResultErrorConstructor, NoResultError, NoResultErrorConstructor, } from './no-result-error.js' -import { HavingExpressionFactory, HavingInterface } from './having-interface.js' +import { HavingInterface } from './having-interface.js' import { IdentifierNode } from '../operation-node/identifier-node.js' import { Explainable, ExplainFormat } from '../util/explainable.js' -import { parseSetOperation } from '../parser/set-operation-parser.js' +import { + SetOperandExpression, + parseSetOperations, +} from '../parser/set-operation-parser.js' import { AliasedExpression, Expression } from '../expression/expression.js' import { ComparisonOperatorExpression, OperandValueExpressionOrList, - parseHaving, - parseReferentialComparison, - parseWhere, + parseValueBinaryOperationOrExpression, + parseReferentialBinaryOperation, } from '../parser/binary-operation-parser.js' -import { - ExistsExpression, - parseExists, - parseNotExists, -} from '../parser/unary-operation-parser.js' import { KyselyTypeError } from '../util/type-error.js' import { Selectable } from '../util/column-type.js' import { Streamable } from '../util/streamable.js' - -export class SelectQueryBuilder - implements - WhereInterface, +import { ExpressionOrFactory } from '../parser/expression-parser.js' +import { ExpressionWrapper } from '../expression/expression-wrapper.js' +import { SelectQueryBuilderExpression } from './select-query-builder-expression.js' +import { + ValueExpression, + parseValueExpression, +} from '../parser/value-parser.js' +import { FetchModifier } from '../operation-node/fetch-node.js' +import { parseFetch } from '../parser/fetch-parser.js' +import { TopModifier } from '../operation-node/top-node.js' +import { parseTop } from '../parser/top-parser.js' + +export interface SelectQueryBuilder + extends WhereInterface, HavingInterface, - Expression, + SelectQueryBuilderExpression, Compilable, Explainable, - Streamable -{ - readonly #props: SelectQueryBuilderProps - - constructor(props: SelectQueryBuilderProps) { - this.#props = freeze(props) - } - - /** @private */ - get expressionType(): O | undefined { - return undefined - } - - where>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): SelectQueryBuilder - - where(factory: WhereExpressionFactory): SelectQueryBuilder - - where(expression: Expression): SelectQueryBuilder - - where(...args: any[]): any { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithWhere( - this.#props.queryNode, - parseWhere(args) - ), - }) - } - - whereRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithWhere( - this.#props.queryNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - orWhere>( + Streamable { + where< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( lhs: RE, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: VE, ): SelectQueryBuilder - orWhere( - factory: WhereExpressionFactory + where>( + expression: E, ): SelectQueryBuilder - orWhere(expression: Expression): SelectQueryBuilder - - orWhere(...args: any[]): any { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithOrWhere( - this.#props.queryNode, - parseWhere(args) - ), - }) - } - - orWhereRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithOrWhere( - this.#props.queryNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - whereExists(arg: ExistsExpression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithWhere( - this.#props.queryNode, - parseExists(arg) - ), - }) - } - - whereNotExists(arg: ExistsExpression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithWhere( - this.#props.queryNode, - parseNotExists(arg) - ), - }) - } - - orWhereExists(arg: ExistsExpression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithOrWhere( - this.#props.queryNode, - parseExists(arg) - ), - }) - } - - orWhereNotExists( - arg: ExistsExpression - ): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithOrWhere( - this.#props.queryNode, - parseNotExists(arg) - ), - }) - } - - having>( - lhs: RE, + whereRef< + LRE extends ReferenceExpression, + RRE extends ReferenceExpression, + >( + lhs: LRE, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: RRE, ): SelectQueryBuilder - having( - factory: HavingExpressionFactory - ): SelectQueryBuilder - - having(expression: Expression): SelectQueryBuilder - - having(...args: any[]): any { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithHaving( - this.#props.queryNode, - parseHaving(args) - ), - }) - } - - havingRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithHaving( - this.#props.queryNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - orHaving>( + having< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( lhs: RE, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: VE, ): SelectQueryBuilder - orHaving( - factory: HavingExpressionFactory + having>( + expression: E, ): SelectQueryBuilder - orHaving(expression: Expression): SelectQueryBuilder - - orHaving(...args: any[]): any { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithOrHaving( - this.#props.queryNode, - parseHaving(args) - ), - }) - } - - orHavingRef( - lhs: ReferenceExpression, + havingRef< + LRE extends ReferenceExpression, + RRE extends ReferenceExpression, + >( + lhs: LRE, op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithOrHaving( - this.#props.queryNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - havingExists(arg: ExistsExpression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithHaving( - this.#props.queryNode, - parseExists(arg) - ), - }) - } - - /** - * @deprecated Use {@link havingNotExists} instead. - */ - havingNotExist(arg: ExistsExpression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithHaving( - this.#props.queryNode, - parseNotExists(arg) - ), - }) - } - - havingNotExists( - arg: ExistsExpression - ): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithHaving( - this.#props.queryNode, - parseNotExists(arg) - ), - }) - } - - orHavingExists(arg: ExistsExpression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithOrHaving( - this.#props.queryNode, - parseExists(arg) - ), - }) - } - - orHavingNotExists( - arg: ExistsExpression - ): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithOrHaving( - this.#props.queryNode, - parseNotExists(arg) - ), - }) - } + rhs: RRE, + ): SelectQueryBuilder /** * Adds a select statement to the query. @@ -410,14 +213,14 @@ export class SelectQueryBuilder * * * - * You can provide an alias for the selections by appending `as the_alias` to the selection. + * You can give an alias for selections and tables by appending `as the_alias` to the name: * * ```ts * const persons = await db - * .selectFrom('person') + * .selectFrom('person as p') * .select([ * 'first_name as fn', - * 'person.last_name as ln' + * 'p.last_name as ln' * ]) * .execute() * ``` @@ -427,8 +230,8 @@ export class SelectQueryBuilder * ```sql * select * "first_name" as "fn", - * "person"."last_name" as "ln" - * from "person" + * "p"."last_name" as "ln" + * from "person" as "p" * ``` * * @@ -440,7 +243,7 @@ export class SelectQueryBuilder * import { sql } from 'kysely' * * const persons = await db.selectFrom('person') - * .select(({ selectFrom, or, cmpr }) => [ + * .select(({ eb, selectFrom, or }) => [ * // Select a correlated subquery * selectFrom('pet') * .whereRef('person.id', '=', 'pet.owner_id') @@ -452,8 +255,8 @@ export class SelectQueryBuilder * // Build and select an expression using * // the expression builder * or([ - * cmpr('first_name', '=', 'Jennifer'), - * cmpr('first_name', '=', 'Arnold') + * eb('first_name', '=', 'Jennifer'), + * eb('first_name', '=', 'Arnold') * ]).as('is_jennifer_or_arnold'), * * // Select a raw sql expression @@ -481,6 +284,45 @@ export class SelectQueryBuilder * In case you use the {@link sql} tag you need to specify the type of the expression * (in this example `string`). * + * + * + * Sometimes you can be sure something's not null but Kysely isn't able to infer + * it. For example calling `where('last_name', 'is not', null)` doesn't make + * `last_name` not null in the result type but unless you have other where statements + * you can be sure it's never null. + * + * Kysely has a couple of helpers for dealing with these cases: `$notNull()` and `$narrowType`. + * Both are used in the following example: + * + * ```ts + * import { NotNull } from 'kysely' + * import { jsonObjectFrom } from 'kysely/helpers/postgres' + * + * const persons = db + * .selectFrom('person') + * .select((eb) => [ + * 'last_name', + * // Let's assume we know the person has at least one + * // pet. We can use the `.$notNull()` method to make + * // the expression not null. You could just as well + * // add `pet` to the `$narrowType` call below. + * jsonObjectFrom( + * eb.selectFrom('pet') + * .selectAll() + * .limit(1) + * .whereRef('person.id', '=', 'pet.owner_id') + * ).$notNull().as('pet') + * ]) + * .where('last_name', 'is not', null) + * // $narrowType can be used to narrow the output type. + * // The special `NotNull` type can be used to make a + * // selection not null. You could add `pet: NotNull` + * // here and omit the `$notNull()` call on it. + * // Use whichever way you prefer. + * .$narrowType<{ last_name: NotNull }>() + * .execute() + * ``` + * * All the examples above assume you know the column names at compile time. * While it's better to build your code like that (that way you also know * the types) sometimes it's not possible or you just prefer to write more @@ -519,16 +361,16 @@ export class SelectQueryBuilder * ``` */ select>( - selection: SelectArg - ): SelectQueryBuilder> { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithSelections( - this.#props.queryNode, - parseSelectArg(selection) - ), - }) - } + selections: ReadonlyArray, + ): SelectQueryBuilder> + + select>( + callback: CB, + ): SelectQueryBuilder> + + select>( + selection: SE, + ): SelectQueryBuilder> /** * Adds `distinct on` expressions to the select clause. @@ -556,23 +398,13 @@ export class SelectQueryBuilder * ``` */ distinctOn>( - selections: ReadonlyArray + selections: ReadonlyArray, ): SelectQueryBuilder distinctOn>( - selection: RE + selection: RE, ): SelectQueryBuilder - distinctOn(selection: ReferenceExpressionOrList): any { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithDistinctOn( - this.#props.queryNode, - parseReferenceExpressionOrList(selection) - ), - }) - } - /** * This can be used to add any additional SQL to the front of the query __after__ the `select` keyword. * @@ -592,15 +424,7 @@ export class SelectQueryBuilder * from `person` * ``` */ - modifyFront(modifier: Expression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithFrontModifier( - this.#props.queryNode, - SelectModifierNode.createWithExpression(modifier.toOperationNode()) - ), - }) - } + modifyFront(modifier: Expression): SelectQueryBuilder /** * This can be used to add any additional SQL to the end of the query. @@ -625,15 +449,7 @@ export class SelectQueryBuilder * for update * ``` */ - modifyEnd(modifier: Expression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithEndModifier( - this.#props.queryNode, - SelectModifierNode.createWithExpression(modifier.toOperationNode()) - ), - }) - } + modifyEnd(modifier: Expression): SelectQueryBuilder /** * Makes the selection distinct. @@ -655,93 +471,37 @@ export class SelectQueryBuilder * select distinct "first_name" from "person" * ``` */ - distinct(): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithFrontModifier( - this.#props.queryNode, - SelectModifierNode.create('Distinct') - ), - }) - } + distinct(): SelectQueryBuilder /** * Adds the `for update` modifier to a select query on supported databases. */ - forUpdate(): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithEndModifier( - this.#props.queryNode, - SelectModifierNode.create('ForUpdate') - ), - }) - } + forUpdate(of?: TableOrList): SelectQueryBuilder /** * Adds the `for share` modifier to a select query on supported databases. */ - forShare(): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithEndModifier( - this.#props.queryNode, - SelectModifierNode.create('ForShare') - ), - }) - } + forShare(of?: TableOrList): SelectQueryBuilder /** * Adds the `for key share` modifier to a select query on supported databases. */ - forKeyShare(): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithEndModifier( - this.#props.queryNode, - SelectModifierNode.create('ForKeyShare') - ), - }) - } + forKeyShare(of?: TableOrList): SelectQueryBuilder /** * Adds the `for no key update` modifier to a select query on supported databases. */ - forNoKeyUpdate(): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithEndModifier( - this.#props.queryNode, - SelectModifierNode.create('ForNoKeyUpdate') - ), - }) - } + forNoKeyUpdate(of?: TableOrList): SelectQueryBuilder /** * Adds the `skip locked` modifier to a select query on supported databases. */ - skipLocked(): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithEndModifier( - this.#props.queryNode, - SelectModifierNode.create('SkipLocked') - ), - }) - } + skipLocked(): SelectQueryBuilder /** * Adds the `nowait` modifier to a select query on supported databases. */ - noWait(): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithEndModifier( - this.#props.queryNode, - SelectModifierNode.create('NoWait') - ), - }) - } + noWait(): SelectQueryBuilder /** * Adds a `select *` or `select table.*` clause to the query. @@ -798,25 +558,15 @@ export class SelectQueryBuilder * ``` */ selectAll( - table: ReadonlyArray + table: ReadonlyArray, ): SelectQueryBuilder> selectAll( - table: T - ): SelectQueryBuilder> + table: T, + ): SelectQueryBuilder> selectAll(): SelectQueryBuilder> - selectAll(table?: any): any { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithSelections( - this.#props.queryNode, - parseSelectAll(table) - ), - }) - } - /** * Joins another table to the query using an inner join. * @@ -873,8 +623,10 @@ export class SelectQueryBuilder * builder for creating more complex joins. The join builder has a * bunch of `on*` methods for building the `on` clause of the join. * There's basically an equivalent for every `where` method - * (`on`, `onRef` etc.). You can do all the same things with the - * `on` method that you can with the corresponding `where` method. + * (`on`, `onRef` etc.). + * + * You can do all the same things with the + * `on` method that you can with the corresponding `where` method (like [OR expressions for example](https://kysely.dev/docs/examples/WHERE/or-where)). * See the `where` method documentation for more examples. * * ```ts @@ -884,6 +636,10 @@ export class SelectQueryBuilder * (join) => join * .onRef('pet.owner_id', '=', 'person.id') * .on('pet.name', '=', 'Doggo') + * .on((eb) => eb.or([ + * eb('person.age', '>', 18), + * eb('person.age', '<', 100) + * ])) * ) * .selectAll() * .execute() @@ -897,6 +653,10 @@ export class SelectQueryBuilder * inner join "pet" * on "pet"."owner_id" = "person"."id" * and "pet"."name" = $1 + * and ( + * "person"."age" > $2 + * OR "person"."age" < $3 + * ) * ``` * * @@ -934,23 +694,20 @@ export class SelectQueryBuilder innerJoin< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression - >(table: TE, k1: K1, k2: K2): SelectQueryBuilderWithInnerJoin + K2 extends JoinReferenceExpression, + >( + table: TE, + k1: K1, + k2: K2, + ): SelectQueryBuilderWithInnerJoin innerJoin< TE extends TableExpression, - FN extends JoinCallbackExpression - >(table: TE, callback: FN): SelectQueryBuilderWithInnerJoin - - innerJoin(...args: any): any { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithJoin( - this.#props.queryNode, - parseJoin('InnerJoin', args) - ), - }) - } + FN extends JoinCallbackExpression, + >( + table: TE, + callback: FN, + ): SelectQueryBuilderWithInnerJoin /** * Just like {@link innerJoin} but adds a left join instead of an inner join. @@ -958,23 +715,20 @@ export class SelectQueryBuilder leftJoin< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression - >(table: TE, k1: K1, k2: K2): SelectQueryBuilderWithLeftJoin + K2 extends JoinReferenceExpression, + >( + table: TE, + k1: K1, + k2: K2, + ): SelectQueryBuilderWithLeftJoin leftJoin< TE extends TableExpression, - FN extends JoinCallbackExpression - >(table: TE, callback: FN): SelectQueryBuilderWithLeftJoin - - leftJoin(...args: any): any { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithJoin( - this.#props.queryNode, - parseJoin('LeftJoin', args) - ), - }) - } + FN extends JoinCallbackExpression, + >( + table: TE, + callback: FN, + ): SelectQueryBuilderWithLeftJoin /** * Just like {@link innerJoin} but adds a right join instead of an inner join. @@ -982,23 +736,20 @@ export class SelectQueryBuilder rightJoin< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression - >(table: TE, k1: K1, k2: K2): SelectQueryBuilderWithRightJoin + K2 extends JoinReferenceExpression, + >( + table: TE, + k1: K1, + k2: K2, + ): SelectQueryBuilderWithRightJoin rightJoin< TE extends TableExpression, - FN extends JoinCallbackExpression - >(table: TE, callback: FN): SelectQueryBuilderWithRightJoin - - rightJoin(...args: any): any { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithJoin( - this.#props.queryNode, - parseJoin('RightJoin', args) - ), - }) - } + FN extends JoinCallbackExpression, + >( + table: TE, + callback: FN, + ): SelectQueryBuilderWithRightJoin /** * Just like {@link innerJoin} but adds a full join instead of an inner join. @@ -1006,23 +757,20 @@ export class SelectQueryBuilder fullJoin< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression - >(table: TE, k1: K1, k2: K2): SelectQueryBuilderWithFullJoin + K2 extends JoinReferenceExpression, + >( + table: TE, + k1: K1, + k2: K2, + ): SelectQueryBuilderWithFullJoin fullJoin< TE extends TableExpression, - FN extends JoinCallbackExpression - >(table: TE, callback: FN): SelectQueryBuilderWithFullJoin - - fullJoin(...args: any): any { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithJoin( - this.#props.queryNode, - parseJoin('FullJoin', args) - ), - }) - } + FN extends JoinCallbackExpression, + >( + table: TE, + callback: FN, + ): SelectQueryBuilderWithFullJoin /** * Just like {@link innerJoin} but adds a lateral join instead of an inner join. @@ -1046,23 +794,20 @@ export class SelectQueryBuilder innerJoinLateral< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression - >(table: TE, k1: K1, k2: K2): SelectQueryBuilderWithInnerJoin + K2 extends JoinReferenceExpression, + >( + table: TE, + k1: K1, + k2: K2, + ): SelectQueryBuilderWithInnerJoin innerJoinLateral< TE extends TableExpression, - FN extends JoinCallbackExpression - >(table: TE, callback: FN): SelectQueryBuilderWithInnerJoin - - innerJoinLateral(...args: any): any { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithJoin( - this.#props.queryNode, - parseJoin('LateralInnerJoin', args) - ), - }) - } + FN extends JoinCallbackExpression, + >( + table: TE, + callback: FN, + ): SelectQueryBuilderWithInnerJoin /** * Just like {@link innerJoin} but adds a lateral left join instead of an inner join. @@ -1085,35 +830,46 @@ export class SelectQueryBuilder leftJoinLateral< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression - >(table: TE, k1: K1, k2: K2): SelectQueryBuilderWithLeftJoin + K2 extends JoinReferenceExpression, + >( + table: TE, + k1: K1, + k2: K2, + ): SelectQueryBuilderWithLeftJoin leftJoinLateral< TE extends TableExpression, - FN extends JoinCallbackExpression - >(table: TE, callback: FN): SelectQueryBuilderWithLeftJoin - - leftJoinLateral(...args: any): any { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithJoin( - this.#props.queryNode, - parseJoin('LateralLeftJoin', args) - ), - }) - } + FN extends JoinCallbackExpression, + >( + table: TE, + callback: FN, + ): SelectQueryBuilderWithLeftJoin /** * Adds an `order by` clause to the query. * - * `orderBy` calls are additive. To order by multiple columns, call `orderBy` - * multiple times. + * `orderBy` calls are additive. Meaning, additional `orderBy` calls append to + * the existing order by clause. + * + * In a single call you can add a single column/expression or multiple columns/expressions. * - * The first argument is the expression to order by and the second is the - * order (`asc` or `desc`). + * Single column/expression calls can have 1-2 arguments. The first argument is + * the expression to order by (optionally including the direction) while the second + * optional argument is the direction (`asc` or `desc`). * * ### Examples * + * Single column/expression per call: + * + * ```ts + * await db + * .selectFrom('person') + * .select('person.first_name as fn') + * .orderBy('id') + * .orderBy('fn desc') + * .execute() + * ``` + * * ```ts * await db * .selectFrom('person') @@ -1131,6 +887,16 @@ export class SelectQueryBuilder * order by "id" asc, "fn" desc * ``` * + * Multiple columns/expressions per call: + * + * ```ts + * await db + * .selectFrom('person') + * .select('person.first_name as fn') + * .orderBy(['id', 'fn desc']) + * .execute() + * ``` + * * The order by expression can also be a raw sql expression or a subquery * in addition to column references: * @@ -1146,7 +912,7 @@ export class SelectQueryBuilder * .limit(1) * ) * .orderBy( - * sql`concat(first_name, last_name)` + * sql`concat(first_name, last_name)` * ) * .execute() * ``` @@ -1190,18 +956,18 @@ export class SelectQueryBuilder * order by "fn" asc * ``` */ - orderBy( - orderBy: OrderByExpression, - direction?: OrderByDirectionExpression - ): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithOrderByItem( - this.#props.queryNode, - parseOrderBy(orderBy, direction) - ), - }) - } + orderBy>( + orderBy: OE, + direction?: OrderByDirectionExpression, + ): SelectQueryBuilder + + orderBy>( + ref: OE, + ): SelectQueryBuilder + + orderBy>( + refs: ReadonlyArray, + ): SelectQueryBuilder /** * Adds a `group by` clause to the query. @@ -1215,7 +981,7 @@ export class SelectQueryBuilder * .selectFrom('person') * .select([ * 'first_name', - * sql`max(id)`.as('max_id') + * sql`max(id)`.as('max_id') * ]) * .groupBy('first_name') * .execute() @@ -1239,7 +1005,7 @@ export class SelectQueryBuilder * .select([ * 'first_name', * 'last_name', - * sql`max(id)`.as('max_id') + * sql`max(id)`.as('max_id') * ]) * .groupBy([ * 'first_name', @@ -1267,10 +1033,10 @@ export class SelectQueryBuilder * .select([ * 'first_name', * 'last_name', - * sql`max(id)`.as('max_id') + * sql`max(id)`.as('max_id') * ]) * .groupBy([ - * sql`concat(first_name, last_name)`, + * sql`concat(first_name, last_name)`, * (qb) => qb.selectFrom('pet').select('id').limit(1) * ]) * .execute() @@ -1301,15 +1067,9 @@ export class SelectQueryBuilder * group by "first_name" * ``` */ - groupBy(groupBy: GroupByArg): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithGroupByItems( - this.#props.queryNode, - parseGroupBy(groupBy) - ), - }) - } + groupBy>( + groupBy: GE, + ): SelectQueryBuilder /** * Adds a limit clause to the query. @@ -1323,6 +1083,13 @@ export class SelectQueryBuilder * .selectFrom('person') * .select('first_name') * .limit(10) + * .execute() + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * select "first_name" from "person" limit $1 * ``` * * Select rows from index 10 to index 19 of the result: @@ -1331,22 +1098,23 @@ export class SelectQueryBuilder * return await db * .selectFrom('person') * .select('first_name') - * .offset(10) * .limit(10) + * .offset(10) + * .execute() + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * select "first_name" from "person" limit $1 offset $2 * ``` */ - limit(limit: number): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithLimit( - this.#props.queryNode, - LimitNode.create(limit) - ), - }) - } + limit( + limit: ValueExpression, + ): SelectQueryBuilder /** - * Adds an offset clause to the query. + * Adds an `offset` clause to the query. * * ### Examples * @@ -1356,19 +1124,97 @@ export class SelectQueryBuilder * return await db * .selectFrom('person') * .select('first_name') - * .offset(10) * .limit(10) + * .offset(10) + * .execute() + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * select "first_name" from "person" limit $1 offset $2 * ``` */ - offset(offset: number): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithOffset( - this.#props.queryNode, - OffsetNode.create(offset) - ), - }) - } + offset( + offset: ValueExpression, + ): SelectQueryBuilder + + /** + * Adds a `fetch` clause to the query. + * + * This clause is only supported by some dialects like PostgreSQL or MS SQL Server. + * + * ### Examples + * + * ```ts + * return await db + * .selectFrom('person') + * .select('first_name') + * .orderBy('first_name') + * .offset(0) + * .fetch(10) + * .execute() + * ``` + * + * The generated SQL (MS SQL Server): + * + * ```sql + * select "first_name" + * from "person" + * order by "first_name" + * offset 0 rows + * fetch next 10 rows only + * ``` + */ + fetch( + rowCount: number | bigint, + modifier?: FetchModifier, + ): SelectQueryBuilder + + /** + * Adds a `top` clause to the query. + * + * This clause is only supported by some dialects like MS SQL Server. + * + * ### Examples + * + * Select 10 biggest ages: + * + * ```ts + * return await db + * .selectFrom('person') + * .select('age') + * .top(10) + * .orderBy('age desc') + * .execute() + * ``` + * + * The generated SQL (MS SQL Server): + * + * ```sql + * select top(10) "age" from "person" order by "age" desc + * ``` + * + * Select 10% first rows: + * + * ```ts + * return await db + * .selectFrom('person') + * .selectAll() + * .top(10, 'percent') + * .execute() + * ``` + * + * The generated SQL (MS SQL Server): + * + * ```sql + * select top(10) percent * from "person" + * ``` + */ + top( + expression: number | bigint, + modifiers?: TopModifier, + ): SelectQueryBuilder /** * Combines another select query or raw expression to this query using `union`. @@ -1383,16 +1229,22 @@ export class SelectQueryBuilder * .union(db.selectFrom('pet').select(['id', 'name'])) * .orderBy('name') * ``` + * + * You can provide a callback to get an expression builder. + * In the following example, this allows us to wrap the query in parentheses: + * + * ```ts + * db.selectFrom('person') + * .select(['id', 'first_name as name']) + * .union((eb) => eb.parens( + * eb.selectFrom('pet').select(['id', 'name']) + * )) + * .orderBy('name') + * ``` */ - union(expression: Expression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithSetOperation( - this.#props.queryNode, - parseSetOperation('union', expression, false) - ), - }) - } + union>( + expression: E, + ): SelectQueryBuilder /** * Combines another select query or raw expression to this query using `union all`. @@ -1407,16 +1259,22 @@ export class SelectQueryBuilder * .unionAll(db.selectFrom('pet').select(['id', 'name'])) * .orderBy('name') * ``` + * + * You can provide a callback to get an expression builder. + * In the following example, this allows us to wrap the query in parentheses: + * + * ```ts + * db.selectFrom('person') + * .select(['id', 'first_name as name']) + * .unionAll((eb) => eb.parens( + * eb.selectFrom('pet').select(['id', 'name']) + * )) + * .orderBy('name') + * ``` */ - unionAll(expression: Expression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithSetOperation( - this.#props.queryNode, - parseSetOperation('union', expression, true) - ), - }) - } + unionAll>( + expression: E, + ): SelectQueryBuilder /** * Combines another select query or raw expression to this query using `intersect`. @@ -1431,16 +1289,22 @@ export class SelectQueryBuilder * .intersect(db.selectFrom('pet').select(['id', 'name'])) * .orderBy('name') * ``` + * + * You can provide a callback to get an expression builder. + * In the following example, this allows us to wrap the query in parentheses: + * + * ```ts + * db.selectFrom('person') + * .select(['id', 'first_name as name']) + * .intersect((eb) => eb.parens( + * eb.selectFrom('pet').select(['id', 'name']) + * )) + * .orderBy('name') + * ``` */ - intersect(expression: Expression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithSetOperation( - this.#props.queryNode, - parseSetOperation('intersect', expression, false) - ), - }) - } + intersect>( + expression: E, + ): SelectQueryBuilder /** * Combines another select query or raw expression to this query using `intersect all`. @@ -1455,16 +1319,22 @@ export class SelectQueryBuilder * .intersectAll(db.selectFrom('pet').select(['id', 'name'])) * .orderBy('name') * ``` + * + * You can provide a callback to get an expression builder. + * In the following example, this allows us to wrap the query in parentheses: + * + * ```ts + * db.selectFrom('person') + * .select(['id', 'first_name as name']) + * .intersectAll((eb) => eb.parens( + * eb.selectFrom('pet').select(['id', 'name']) + * )) + * .orderBy('name') + * ``` */ - intersectAll(expression: Expression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithSetOperation( - this.#props.queryNode, - parseSetOperation('intersect', expression, true) - ), - }) - } + intersectAll>( + expression: E, + ): SelectQueryBuilder /** * Combines another select query or raw expression to this query using `except`. @@ -1479,16 +1349,22 @@ export class SelectQueryBuilder * .except(db.selectFrom('pet').select(['id', 'name'])) * .orderBy('name') * ``` + * + * You can provide a callback to get an expression builder. + * In the following example, this allows us to wrap the query in parentheses: + * + * ```ts + * db.selectFrom('person') + * .select(['id', 'first_name as name']) + * .except((eb) => eb.parens( + * eb.selectFrom('pet').select(['id', 'name']) + * )) + * .orderBy('name') + * ``` */ - except(expression: Expression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithSetOperation( - this.#props.queryNode, - parseSetOperation('except', expression, false) - ), - }) - } + except>( + expression: E, + ): SelectQueryBuilder /** * Combines another select query or raw expression to this query using `except all`. @@ -1503,16 +1379,22 @@ export class SelectQueryBuilder * .exceptAll(db.selectFrom('pet').select(['id', 'name'])) * .orderBy('name') * ``` + * + * You can provide a callback to get an expression builder. + * In the following example, this allows us to wrap the query in parentheses: + * + * ```ts + * db.selectFrom('person') + * .select(['id', 'first_name as name']) + * .exceptAll((eb) => eb.parens( + * eb.selectFrom('pet').select(['id', 'name']) + * )) + * .orderBy('name') + * ``` */ - exceptAll(expression: Expression): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithSetOperation( - this.#props.queryNode, - parseSetOperation('except', expression, true) - ), - }) - } + exceptAll>( + expression: E, + ): SelectQueryBuilder /** * Gives an alias for the query. This method is only useful for sub queries. @@ -1533,9 +1415,7 @@ export class SelectQueryBuilder * pets[0].owner_first_name * ``` */ - as(alias: A): AliasedSelectQueryBuilder { - return new AliasedSelectQueryBuilder(this, alias) - } + as(alias: A): AliasedSelectQueryBuilder /** * Clears all select clauses from the query. @@ -1555,19 +1435,9 @@ export class SelectQueryBuilder * select "id", "gender" from "person" * ``` */ - clearSelect(): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithoutSelections(this.#props.queryNode), - }) - } + clearSelect(): SelectQueryBuilder - clearWhere(): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithoutWhere(this.#props.queryNode), - }) - } + clearWhere(): SelectQueryBuilder /** * Clears limit clause from the query. @@ -1587,12 +1457,7 @@ export class SelectQueryBuilder * select * from "person" * ``` */ - clearLimit(): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithoutLimit(this.#props.queryNode), - }) - } + clearLimit(): SelectQueryBuilder /** * Clears offset clause from the query. @@ -1613,12 +1478,7 @@ export class SelectQueryBuilder * select * from "person" limit 10 * ``` */ - clearOffset(): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithoutOffset(this.#props.queryNode), - }) - } + clearOffset(): SelectQueryBuilder /** * Clears all `order by` clauses from the query. @@ -1638,12 +1498,27 @@ export class SelectQueryBuilder * select * from "person" * ``` */ - clearOrderBy(): SelectQueryBuilder { - return new SelectQueryBuilder({ - ...this.#props, - queryNode: SelectQueryNode.cloneWithoutOrderBy(this.#props.queryNode), - }) - } + clearOrderBy(): SelectQueryBuilder + + /** + * Clears `group by` clause from the query. + * + * ### Examples + * + * ```ts + * db.selectFrom('person') + * .selectAll() + * .groupBy('id') + * .clearGroupBy() + * ``` + * + * The generated SQL(PostgreSQL): + * + * ```sql + * select * from "person" + * ``` + */ + clearGroupBy(): SelectQueryBuilder /** * Simply calls the provided function passing `this` as the only argument. `$call` returns @@ -1668,16 +1543,7 @@ export class SelectQueryBuilder * .execute() * ``` */ - $call(func: (qb: this) => T): T { - return func(this) - } - - /** - * @deprecated Use `$call` instead - */ - call(func: (qb: this) => T): T { - return this.$call(func) - } + $call(func: (qb: this) => T): T /** * Call `func(this)` if `condition` is true. @@ -1734,57 +1600,121 @@ export class SelectQueryBuilder * You can also call any other methods inside the callback: * * ```ts - * const { count } = db.fn - * * db.selectFrom('person') * .select('person.id') * .$if(filterByFirstName, (qb) => qb.where('first_name', '=', firstName)) * .$if(filterByPetCount, (qb) => qb * .innerJoin('pet', 'pet.owner_id', 'person.id') - * .having(count('pet.id'), '>', petCountLimit) + * .having((eb) => eb.fn.count('pet.id'), '>', petCountLimit) * .groupBy('person.id') * ) * ``` */ $if( condition: boolean, - func: (qb: this) => SelectQueryBuilder - ): SelectQueryBuilder> { - if (condition) { - return func(this) - } - - return new SelectQueryBuilder({ - ...this.#props, - }) - } - - /** - * @deprecated Use `$if` instead - */ - if( - condition: boolean, - func: (qb: this) => SelectQueryBuilder - ): SelectQueryBuilder> { - return this.$if(condition, func) - } + func: (qb: this) => SelectQueryBuilder, + ): SelectQueryBuilder>> /** * Change the output type of the query. * - * You should only use this method as the last resort if the types - * don't support your use case. + * This method call doesn't change the SQL in any way. This methods simply + * returns a copy of this `SelectQueryBuilder` with a new output type. */ - $castTo(): SelectQueryBuilder { - return new SelectQueryBuilder(this.#props) - } + $castTo(): SelectQueryBuilder /** - * @deprecated Use `$castTo` instead. + * Changes the output type from an object to a tuple. + * + * This doesn't affect the generated SQL in any way. This function is + * just a necessary evil when you need to convert a query's output + * record type to a tuple type. Typescript doesn't currently offer + * tools to do this automatically (without insane hackery). + * + * The returned object can no longer be executed. It can only be used + * as a subquery. + * + * ### Examples + * + * ```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('pet.species', '!=', 'cat') + * .$asTuple('name', 'species') + * )) + * ``` + * + * The generated SQL(PostgreSQL): + * + * ```sql + * select + * "person".* + * from + * "person" + * where + * ("first_name", "last_name") + * in + * ( + * select "name", "species" + * from "pet" + * where "pet"."species" != $1 + * ) + * ``` */ - castTo(): SelectQueryBuilder { - return this.$castTo() - } + $asTuple>( + key1: K1, + key2: K2, + ): keyof O extends K1 | K2 + ? ExpressionWrapper + : KyselyTypeError<'$asTuple() call failed: All selected columns must be provided as arguments'> + + $asTuple< + K1 extends keyof O, + K2 extends Exclude, + K3 extends Exclude, + >( + key1: K1, + key2: K2, + key3: K3, + ): keyof O extends K1 | K2 | K3 + ? ExpressionWrapper + : KyselyTypeError<'$asTuple() call failed: All selected columns must be provided as arguments'> + + $asTuple< + K1 extends keyof O, + K2 extends Exclude, + K3 extends Exclude, + K4 extends Exclude, + >( + key1: K1, + key2: K2, + key3: K3, + key4: K4, + ): keyof O extends K1 | K2 | K3 | K4 + ? ExpressionWrapper + : KyselyTypeError<'$asTuple() call failed: All selected columns must be provided as arguments'> + + $asTuple< + K1 extends keyof O, + K2 extends Exclude, + K3 extends Exclude, + K4 extends Exclude, + K5 extends Exclude, + >( + key1: K1, + key2: K2, + key3: K3, + key4: K4, + key5: K5, + ): keyof O extends K1 | K2 | K3 | K4 | K5 + ? ExpressionWrapper + : KyselyTypeError<'$asTuple() call failed: All selected columns must be provided as arguments'> /** * Narrows (parts of) the output type of the query. @@ -1825,10 +1755,24 @@ export class SelectQueryBuilder * * functionThatExpectsPersonWithNonNullValue(person) * ``` + * + * Giving the explicit narrowed type (`string` in the example above) works fine for + * simple types. If the type is complex, for example a JSON column or a subquery, + * you can use the special `NotNull` type to make the column not null. + * + * ```ts + * import { NotNull } from 'kysely' + * + * const person = await db.selectFrom('person') + * .where('nullable_column', 'is not', null) + * .selectAll() + * .$narrowType<{ nullable_column: NotNull }>() + * .executeTakeFirstOrThrow() + * + * functionThatExpectsPersonWithNonNullValue(person) + * ``` */ - $narrowType(): SelectQueryBuilder> { - return new SelectQueryBuilder(this.#props) - } + $narrowType(): SelectQueryBuilder> /** * Asserts that query's output row type equals the given type `T`. @@ -1871,24 +1815,534 @@ export class SelectQueryBuilder */ $assertType(): O extends T ? SelectQueryBuilder - : KyselyTypeError<`$assertType() call failed: The type passed in is not equal to the output type of the query.`> { - return new SelectQueryBuilder(this.#props) as unknown as any - } + : KyselyTypeError<`$assertType() call failed: The type passed in is not equal to the output type of the query.`> /** - * @deprecated Use `$assertType` instead. + * Returns a copy of this SelectQueryBuilder instance with the given plugin installed. */ - assertType(): O extends T - ? SelectQueryBuilder - : KyselyTypeError<`assertType() call failed: The type passed in is not equal to the output type of the query.`> { - return new SelectQueryBuilder(this.#props) as unknown as any - } + withPlugin(plugin: KyselyPlugin): SelectQueryBuilder + + toOperationNode(): SelectQueryNode + + compile(): CompiledQuery> /** - * Returns a copy of this SelectQueryBuilder instance with the given plugin installed. + * Executes the query and returns an array of rows. + * + * Also see the {@link executeTakeFirst} and {@link executeTakeFirstOrThrow} methods. + */ + execute(): Promise[]> + + /** + * Executes the query and returns the first result or undefined if + * the query returned no result. + */ + executeTakeFirst(): Promise> + + /** + * 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 to throw a different + * error. */ + executeTakeFirstOrThrow( + errorConstructor?: NoResultErrorConstructor | ((node: QueryNode) => Error), + ): Promise> + + stream(chunkSize?: number): AsyncIterableIterator + + explain = Record>( + format?: ExplainFormat, + options?: Expression, + ): Promise +} + +class SelectQueryBuilderImpl + implements SelectQueryBuilder +{ + readonly #props: SelectQueryBuilderProps + + constructor(props: SelectQueryBuilderProps) { + this.#props = freeze(props) + } + + get expressionType(): O | undefined { + return undefined + } + + get isSelectQueryBuilder(): true { + return true + } + + where(...args: any[]): any { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: QueryNode.cloneWithWhere( + this.#props.queryNode, + parseValueBinaryOperationOrExpression(args), + ), + }) + } + + whereRef( + lhs: ReferenceExpression, + op: ComparisonOperatorExpression, + rhs: ReferenceExpression, + ): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: QueryNode.cloneWithWhere( + this.#props.queryNode, + parseReferentialBinaryOperation(lhs, op, rhs), + ), + }) + } + + having(...args: any[]): any { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithHaving( + this.#props.queryNode, + parseValueBinaryOperationOrExpression(args), + ), + }) + } + + havingRef( + lhs: ReferenceExpression, + op: ComparisonOperatorExpression, + rhs: ReferenceExpression, + ): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithHaving( + this.#props.queryNode, + parseReferentialBinaryOperation(lhs, op, rhs), + ), + }) + } + + select>( + selection: SelectArg, + ): SelectQueryBuilder> { + return new SelectQueryBuilderImpl>({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithSelections( + this.#props.queryNode, + parseSelectArg(selection), + ), + }) + } + + distinctOn(selection: ReferenceExpressionOrList): any { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithDistinctOn( + this.#props.queryNode, + parseReferenceExpressionOrList(selection), + ), + }) + } + + modifyFront(modifier: Expression): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithFrontModifier( + this.#props.queryNode, + SelectModifierNode.createWithExpression(modifier.toOperationNode()), + ), + }) + } + + modifyEnd(modifier: Expression): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithEndModifier( + this.#props.queryNode, + SelectModifierNode.createWithExpression(modifier.toOperationNode()), + ), + }) + } + + distinct(): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithFrontModifier( + this.#props.queryNode, + SelectModifierNode.create('Distinct'), + ), + }) + } + + forUpdate(of?: TableOrList): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithEndModifier( + this.#props.queryNode, + SelectModifierNode.create( + 'ForUpdate', + of ? asArray(of).map(parseTable) : undefined, + ), + ), + }) + } + + forShare(of?: TableOrList): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithEndModifier( + this.#props.queryNode, + SelectModifierNode.create( + 'ForShare', + of ? asArray(of).map(parseTable) : undefined, + ), + ), + }) + } + + forKeyShare(of?: TableOrList): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithEndModifier( + this.#props.queryNode, + SelectModifierNode.create( + 'ForKeyShare', + of ? asArray(of).map(parseTable) : undefined, + ), + ), + }) + } + + forNoKeyUpdate(of?: TableOrList): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithEndModifier( + this.#props.queryNode, + SelectModifierNode.create( + 'ForNoKeyUpdate', + of ? asArray(of).map(parseTable) : undefined, + ), + ), + }) + } + + skipLocked(): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithEndModifier( + this.#props.queryNode, + SelectModifierNode.create('SkipLocked'), + ), + }) + } + + noWait(): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithEndModifier( + this.#props.queryNode, + SelectModifierNode.create('NoWait'), + ), + }) + } + + selectAll(table?: any): any { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithSelections( + this.#props.queryNode, + parseSelectAll(table), + ), + }) + } + + innerJoin(...args: any): any { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: QueryNode.cloneWithJoin( + this.#props.queryNode, + parseJoin('InnerJoin', args), + ), + }) + } + + leftJoin(...args: any): any { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: QueryNode.cloneWithJoin( + this.#props.queryNode, + parseJoin('LeftJoin', args), + ), + }) + } + + rightJoin(...args: any): any { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: QueryNode.cloneWithJoin( + this.#props.queryNode, + parseJoin('RightJoin', args), + ), + }) + } + + fullJoin(...args: any): any { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: QueryNode.cloneWithJoin( + this.#props.queryNode, + parseJoin('FullJoin', args), + ), + }) + } + + innerJoinLateral(...args: any): any { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: QueryNode.cloneWithJoin( + this.#props.queryNode, + parseJoin('LateralInnerJoin', args), + ), + }) + } + + leftJoinLateral(...args: any): any { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: QueryNode.cloneWithJoin( + this.#props.queryNode, + parseJoin('LateralLeftJoin', args), + ), + }) + } + + orderBy(...args: any[]): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithOrderByItems( + this.#props.queryNode, + parseOrderBy(args), + ), + }) + } + + groupBy(groupBy: GroupByArg): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithGroupByItems( + this.#props.queryNode, + parseGroupBy(groupBy), + ), + }) + } + + limit( + limit: ValueExpression, + ): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithLimit( + this.#props.queryNode, + LimitNode.create(parseValueExpression(limit)), + ), + }) + } + + offset( + offset: ValueExpression, + ): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithOffset( + this.#props.queryNode, + OffsetNode.create(parseValueExpression(offset)), + ), + }) + } + + fetch( + rowCount: number | bigint, + modifier: FetchModifier = 'only', + ): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithFetch( + this.#props.queryNode, + parseFetch(rowCount, modifier), + ), + }) + } + + top( + expression: number | bigint, + modifiers?: TopModifier, + ): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: QueryNode.cloneWithTop( + this.#props.queryNode, + parseTop(expression, modifiers), + ), + }) + } + + union( + expression: SetOperandExpression, + ): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithSetOperations( + this.#props.queryNode, + parseSetOperations('union', expression, false), + ), + }) + } + + unionAll( + expression: SetOperandExpression, + ): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithSetOperations( + this.#props.queryNode, + parseSetOperations('union', expression, true), + ), + }) + } + + intersect( + expression: SetOperandExpression, + ): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithSetOperations( + this.#props.queryNode, + parseSetOperations('intersect', expression, false), + ), + }) + } + + intersectAll( + expression: SetOperandExpression, + ): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithSetOperations( + this.#props.queryNode, + parseSetOperations('intersect', expression, true), + ), + }) + } + + except( + expression: SetOperandExpression, + ): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithSetOperations( + this.#props.queryNode, + parseSetOperations('except', expression, false), + ), + }) + } + + exceptAll( + expression: SetOperandExpression, + ): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithSetOperations( + this.#props.queryNode, + parseSetOperations('except', expression, true), + ), + }) + } + + as(alias: A): AliasedSelectQueryBuilder { + return new AliasedSelectQueryBuilderImpl(this, alias) + } + + clearSelect(): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithoutSelections(this.#props.queryNode), + }) + } + + clearWhere(): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: QueryNode.cloneWithoutWhere(this.#props.queryNode), + }) + } + + clearLimit(): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithoutLimit(this.#props.queryNode), + }) + } + + clearOffset(): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithoutOffset(this.#props.queryNode), + }) + } + + clearOrderBy(): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithoutOrderBy(this.#props.queryNode), + }) + } + + clearGroupBy(): SelectQueryBuilder { + return new SelectQueryBuilderImpl({ + ...this.#props, + queryNode: SelectQueryNode.cloneWithoutGroupBy(this.#props.queryNode), + }) + } + + $call(func: (qb: this) => T): T { + return func(this) + } + + $if( + condition: boolean, + func: (qb: this) => SelectQueryBuilder, + ): SelectQueryBuilder>> { + if (condition) { + return func(this) + } + + return new SelectQueryBuilderImpl({ + ...this.#props, + }) as any + } + + $castTo(): SelectQueryBuilder { + return new SelectQueryBuilderImpl(this.#props) + } + + $narrowType(): SelectQueryBuilder> { + return new SelectQueryBuilderImpl(this.#props) + } + + $assertType(): O extends T + ? SelectQueryBuilder + : KyselyTypeError<`$assertType() call failed: The type passed in is not equal to the output type of the query.`> { + return new SelectQueryBuilderImpl(this.#props) as unknown as any + } + + $asTuple(): ExpressionWrapper { + return new ExpressionWrapper(this.toOperationNode()) + } + withPlugin(plugin: KyselyPlugin): SelectQueryBuilder { - return new SelectQueryBuilder({ + return new SelectQueryBuilderImpl({ ...this.#props, executor: this.#props.executor.withPlugin(plugin), }) @@ -1897,54 +2351,37 @@ export class SelectQueryBuilder toOperationNode(): SelectQueryNode { return this.#props.executor.transformQuery( this.#props.queryNode, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery> { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } - /** - * Executes the query and returns an array of rows. - * - * Also see the {@link executeTakeFirst} and {@link executeTakeFirstOrThrow} methods. - */ async execute(): Promise[]> { const compiledQuery = this.compile() const result = await this.#props.executor.executeQuery( compiledQuery, - this.#props.queryId + this.#props.queryId, ) return result.rows } - /** - * Executes the query and returns the first result or undefined if - * the query returned no result. - */ async executeTakeFirst(): Promise> { const [result] = await this.execute() return result as SimplifySingleResult } - /** - * 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 to throw a different - * error. - */ async executeTakeFirstOrThrow( errorConstructor: | NoResultErrorConstructor - | ((node: QueryNode) => Error) = NoResultError + | ((node: QueryNode) => Error) = NoResultError, ): Promise> { const result = await this.executeTakeFirst() @@ -1965,7 +2402,7 @@ export class SelectQueryBuilder const stream = this.#props.executor.stream( compiledQuery, chunkSize, - this.#props.queryId + this.#props.queryId, ) for await (const item of stream) { @@ -1975,14 +2412,14 @@ export class SelectQueryBuilder async explain = Record>( format?: ExplainFormat, - options?: Expression + options?: Expression, ): Promise { - const builder = new SelectQueryBuilder({ + const builder = new SelectQueryBuilderImpl({ ...this.#props, queryNode: QueryNode.cloneWithExplain( this.#props.queryNode, format, - options + options, ), }) @@ -1991,25 +2428,38 @@ export class SelectQueryBuilder } preventAwait( - SelectQueryBuilder, - "don't await SelectQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`." + SelectQueryBuilderImpl, + "don't await SelectQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`.", ) +export function createSelectQueryBuilder( + props: SelectQueryBuilderProps, +): SelectQueryBuilder { + return new SelectQueryBuilderImpl(props) +} + export interface SelectQueryBuilderProps { readonly queryId: QueryId readonly queryNode: SelectQueryNode readonly executor: QueryExecutor } +export interface AliasedSelectQueryBuilder< + O = undefined, + A extends string = never, +> extends AliasedExpression { + get isAliasedSelectQueryBuilder(): true +} + /** * {@link SelectQueryBuilder} with an alias. The result of calling {@link SelectQueryBuilder.as}. */ -export class AliasedSelectQueryBuilder< +class AliasedSelectQueryBuilderImpl< DB, TB extends keyof DB, O = undefined, - A extends string = never -> implements AliasedExpression + A extends string = never, +> implements AliasedSelectQueryBuilder { readonly #queryBuilder: SelectQueryBuilder readonly #alias: A @@ -2019,29 +2469,36 @@ export class AliasedSelectQueryBuilder< this.#alias = alias } - /** @private */ get expression(): Expression { return this.#queryBuilder } - /** @private */ get alias(): A { return this.#alias } + get isAliasedSelectQueryBuilder(): true { + return true + } + toOperationNode(): AliasNode { return AliasNode.create( this.#queryBuilder.toOperationNode(), - IdentifierNode.create(this.#alias) + IdentifierNode.create(this.#alias), ) } } +preventAwait( + AliasedSelectQueryBuilderImpl, + "don't await AliasedSelectQueryBuilder instances directly. AliasedSelectQueryBuilder should never be executed directly since it's always a part of another query.", +) + export type SelectQueryBuilderWithInnerJoin< DB, TB extends keyof DB, O, - TE extends TableExpression + TE extends TableExpression, > = TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? InnerJoinedBuilder @@ -2059,7 +2516,7 @@ type InnerJoinedBuilder< TB extends keyof DB, O, A extends string, - R + R, > = A extends keyof DB ? SelectQueryBuilder, TB | A, O> : // Much faster non-recursive solution for the simple case. @@ -2073,7 +2530,7 @@ export type SelectQueryBuilderWithLeftJoin< DB, TB extends keyof DB, O, - TE extends TableExpression + TE extends TableExpression, > = TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? LeftJoinedBuilder @@ -2091,7 +2548,7 @@ type LeftJoinedBuilder< TB extends keyof DB, O, A extends keyof any, - R + R, > = A extends keyof DB ? SelectQueryBuilder, TB | A, O> : // Much faster non-recursive solution for the simple case. @@ -2109,7 +2566,7 @@ export type SelectQueryBuilderWithRightJoin< DB, TB extends keyof DB, O, - TE extends TableExpression + TE extends TableExpression, > = TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? RightJoinedBuilder @@ -2127,14 +2584,14 @@ type RightJoinedBuilder< TB extends keyof DB, O, A extends keyof any, - R + R, > = SelectQueryBuilder, TB | A, O> type RightJoinedDB< DB, TB extends keyof DB, A extends keyof any, - R + R, > = DrainOuterGeneric<{ [C in keyof DB | A]: C extends A ? R @@ -2149,7 +2606,7 @@ export type SelectQueryBuilderWithFullJoin< DB, TB extends keyof DB, O, - TE extends TableExpression + TE extends TableExpression, > = TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? OuterJoinedBuilder @@ -2167,14 +2624,14 @@ type OuterJoinedBuilder< TB extends keyof DB, O, A extends keyof any, - R + R, > = SelectQueryBuilder, TB | A, O> type OuterJoinedBuilderDB< DB, TB extends keyof DB, A extends keyof any, - R + R, > = DrainOuterGeneric<{ [C in keyof DB | A]: C extends A ? Nullable @@ -2184,3 +2641,7 @@ type OuterJoinedBuilderDB< ? DB[C] : never }> + +type TableOrList = + | (TB & string) + | ReadonlyArray diff --git a/src/query-builder/update-query-builder.ts b/src/query-builder/update-query-builder.ts index fed0cf8fc..443c0b382 100644 --- a/src/query-builder/update-query-builder.ts +++ b/src/query-builder/update-query-builder.ts @@ -17,8 +17,13 @@ import { parseSelectAll, SelectExpression, SelectArg, + SelectCallback, } from '../parser/select-parser.js' -import { ReturningRow } from '../parser/returning-parser.js' +import { + ReturningAllRow, + ReturningCallbackRow, + ReturningRow, +} from '../parser/returning-parser.js' import { ReferenceExpression } from '../parser/reference-parser.js' import { QueryNode } from '../operation-node/query-node.js' import { @@ -28,13 +33,13 @@ import { ShallowRecord, SimplifyResult, SimplifySingleResult, + SqlBool, } from '../util/type-utils.js' import { UpdateQueryNode } from '../operation-node/update-query-node.js' import { - parseUpdateExpression, - UpdateExpression, - UpdateObject, - UpdateObjectFactory, + UpdateObjectExpression, + ExtractUpdateTypeFromReferenceExpression, + parseUpdate, } from '../parser/update-set-parser.js' import { preventAwait } from '../util/prevent-await.js' import { Compilable } from '../util/compilable.js' @@ -43,7 +48,7 @@ import { QueryId } from '../util/query-id.js' import { freeze } from '../util/object-utils.js' import { UpdateResult } from './update-result.js' import { KyselyPlugin } from '../plugin/kysely-plugin.js' -import { WhereExpressionFactory, WhereInterface } from './where-interface.js' +import { WhereInterface } from './where-interface.js' import { ReturningInterface } from './returning-interface.js' import { isNoResultErrorConstructor, @@ -56,21 +61,32 @@ import { AliasedExpression, Expression } from '../expression/expression.js' import { ComparisonOperatorExpression, OperandValueExpressionOrList, - parseReferentialComparison, - parseWhere, + parseReferentialBinaryOperation, + parseValueBinaryOperationOrExpression, } from '../parser/binary-operation-parser.js' -import { - ExistsExpression, - parseExists, - parseNotExists, -} from '../parser/unary-operation-parser.js' import { KyselyTypeError } from '../util/type-error.js' import { Streamable } from '../util/streamable.js' +import { ExpressionOrFactory } from '../parser/expression-parser.js' +import { + ValueExpression, + parseValueExpression, +} from '../parser/value-parser.js' +import { LimitNode } from '../operation-node/limit-node.js' +import { parseTop } from '../parser/top-parser.js' +import { + OutputCallback, + OutputExpression, + OutputInterface, + OutputPrefix, + SelectExpressionFromOutputCallback, + SelectExpressionFromOutputExpression, +} from './output-interface.js' export class UpdateQueryBuilder implements WhereInterface, ReturningInterface, + OutputInterface, OperationNodeSource, Compilable, Explainable, @@ -82,133 +98,105 @@ export class UpdateQueryBuilder this.#props = freeze(props) } - where>( + where< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( lhs: RE, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: VE, ): UpdateQueryBuilder - where( - factory: WhereExpressionFactory + where>( + expression: E, ): UpdateQueryBuilder - where(expression: Expression): UpdateQueryBuilder - where(...args: any[]): any { return new UpdateQueryBuilder({ ...this.#props, queryNode: QueryNode.cloneWithWhere( this.#props.queryNode, - parseWhere(args) - ), - }) - } - - whereRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): UpdateQueryBuilder { - return new UpdateQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithWhere( - this.#props.queryNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - orWhere>( - lhs: RE, - op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList - ): UpdateQueryBuilder - - orWhere( - factory: WhereExpressionFactory - ): UpdateQueryBuilder - - orWhere(expression: Expression): UpdateQueryBuilder - - orWhere(...args: any[]): any { - return new UpdateQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithOrWhere( - this.#props.queryNode, - parseWhere(args) + parseValueBinaryOperationOrExpression(args), ), }) } - orWhereRef( - lhs: ReferenceExpression, + whereRef< + LRE extends ReferenceExpression, + RRE extends ReferenceExpression, + >( + lhs: LRE, op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): UpdateQueryBuilder { - return new UpdateQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithOrWhere( - this.#props.queryNode, - parseReferentialComparison(lhs, op, rhs) - ), - }) - } - - whereExists( - arg: ExistsExpression - ): UpdateQueryBuilder { - return new UpdateQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithWhere( - this.#props.queryNode, - parseExists(arg) - ), - }) - } - - whereNotExists( - arg: ExistsExpression + rhs: RRE, ): UpdateQueryBuilder { return new UpdateQueryBuilder({ ...this.#props, queryNode: QueryNode.cloneWithWhere( this.#props.queryNode, - parseNotExists(arg) + parseReferentialBinaryOperation(lhs, op, rhs), ), }) } - orWhereExists( - arg: ExistsExpression - ): UpdateQueryBuilder { + clearWhere(): UpdateQueryBuilder { return new UpdateQueryBuilder({ ...this.#props, - queryNode: QueryNode.cloneWithOrWhere( - this.#props.queryNode, - parseExists(arg) - ), + queryNode: QueryNode.cloneWithoutWhere(this.#props.queryNode), }) } - orWhereNotExists( - arg: ExistsExpression + /** + * 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: number | bigint, + modifiers?: 'percent', ): UpdateQueryBuilder { return new UpdateQueryBuilder({ ...this.#props, - queryNode: QueryNode.cloneWithOrWhere( + queryNode: QueryNode.cloneWithTop( this.#props.queryNode, - parseNotExists(arg) + parseTop(expression, modifiers), ), }) } - clearWhere(): UpdateQueryBuilder { - return new UpdateQueryBuilder({ - ...this.#props, - queryNode: QueryNode.cloneWithoutWhere(this.#props.queryNode), - }) - } - /** * Adds a from clause to the update query. * @@ -237,11 +225,11 @@ export class UpdateQueryBuilder * ``` */ from>( - table: TE + table: TE, ): UpdateQueryBuilder, UT, FromTables, O> from>( - table: TE[] + table: TE[], ): UpdateQueryBuilder, UT, FromTables, O> from(from: TableExpressionOrList): any { @@ -249,7 +237,7 @@ export class UpdateQueryBuilder ...this.#props, queryNode: UpdateQueryNode.cloneWithFromItems( this.#props.queryNode, - parseTableExpressionOrList(from) + parseTableExpressionOrList(from), ), }) } @@ -366,16 +354,16 @@ export class UpdateQueryBuilder innerJoin< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression + K2 extends JoinReferenceExpression, >( table: TE, k1: K1, - k2: K2 + k2: K2, ): UpdateQueryBuilderWithInnerJoin innerJoin< TE extends TableExpression, - FN extends JoinCallbackExpression + FN extends JoinCallbackExpression, >(table: TE, callback: FN): UpdateQueryBuilderWithInnerJoin innerJoin(...args: any): any { @@ -383,7 +371,7 @@ export class UpdateQueryBuilder ...this.#props, queryNode: QueryNode.cloneWithJoin( this.#props.queryNode, - parseJoin('InnerJoin', args) + parseJoin('InnerJoin', args), ), }) } @@ -394,16 +382,16 @@ export class UpdateQueryBuilder leftJoin< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression + K2 extends JoinReferenceExpression, >( table: TE, k1: K1, - k2: K2 + k2: K2, ): UpdateQueryBuilderWithLeftJoin leftJoin< TE extends TableExpression, - FN extends JoinCallbackExpression + FN extends JoinCallbackExpression, >(table: TE, callback: FN): UpdateQueryBuilderWithLeftJoin leftJoin(...args: any): any { @@ -411,7 +399,7 @@ export class UpdateQueryBuilder ...this.#props, queryNode: QueryNode.cloneWithJoin( this.#props.queryNode, - parseJoin('LeftJoin', args) + parseJoin('LeftJoin', args), ), }) } @@ -422,16 +410,16 @@ export class UpdateQueryBuilder rightJoin< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression + K2 extends JoinReferenceExpression, >( table: TE, k1: K1, - k2: K2 + k2: K2, ): UpdateQueryBuilderWithRightJoin rightJoin< TE extends TableExpression, - FN extends JoinCallbackExpression + FN extends JoinCallbackExpression, >(table: TE, callback: FN): UpdateQueryBuilderWithRightJoin rightJoin(...args: any): any { @@ -439,7 +427,7 @@ export class UpdateQueryBuilder ...this.#props, queryNode: QueryNode.cloneWithJoin( this.#props.queryNode, - parseJoin('RightJoin', args) + parseJoin('RightJoin', args), ), }) } @@ -450,16 +438,16 @@ export class UpdateQueryBuilder fullJoin< TE extends TableExpression, K1 extends JoinReferenceExpression, - K2 extends JoinReferenceExpression + K2 extends JoinReferenceExpression, >( table: TE, k1: K1, - k2: K2 + k2: K2, ): UpdateQueryBuilderWithFullJoin fullJoin< TE extends TableExpression, - FN extends JoinCallbackExpression + FN extends JoinCallbackExpression, >(table: TE, callback: FN): UpdateQueryBuilderWithFullJoin fullJoin(...args: any): any { @@ -467,7 +455,38 @@ export class UpdateQueryBuilder ...this.#props, queryNode: QueryNode.cloneWithJoin( this.#props.queryNode, - parseJoin('FullJoin', args) + parseJoin('FullJoin', args), + ), + }) + } + + /** + * 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 + * return await db + * .updateTable('person') + * .set({ first_name: 'Foo' }) + * .limit(2); + * ``` + * + * The generated SQL (MySQL): + * ```sql + * update `person` set `first_name` = 'Foo' limit 2 + * ``` + */ + limit( + limit: ValueExpression, + ): UpdateQueryBuilder { + return new UpdateQueryBuilder({ + ...this.#props, + queryNode: UpdateQueryNode.cloneWithLimit( + this.#props.queryNode, + LimitNode.create(parseValueExpression(limit)), ), }) } @@ -512,7 +531,52 @@ export class UpdateQueryBuilder * update "person" set "first_name" = $1, "last_name" = $2 where "id" = $3 * ``` * - * On PostgreSQL you ca chain `returning` to the query to get + * + * + * As always, you can provide a callback to the `set` method to get access + * to an expression builder: + * + * ```ts + * const result = await db + * .updateTable('person') + * .set((eb) => ({ + * age: eb('age', '+', 1), + * first_name: eb.selectFrom('pet').select('name').limit(1), + * last_name: 'updated', + * })) + * .where('id', '=', '1') + * .executeTakeFirst() + * + * console.log(result.numUpdatedRows) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * update "person" + * set + * "first_name" = (select "name" from "pet" limit $1), + * "age" = "age" + $2, + * "last_name" = $3 + * where + * "id" = $4 + * ``` + * + * If you provide two arguments the first one is interpreted as the column + * (or other target) and the second as the value: + * + * ```ts + * const result = await db + * .updateTable('person') + * .set('first_name', 'Foo') + * // As always, both arguments can be arbitrary expressions or + * // callbacks that give you access to an expression builder: + * .set(sql`address['postalCode']`, (eb) => eb.val('61710)) + * .where('id', '=', '1') + * .executeTakeFirst() + * ``` + * + * On PostgreSQL you can chain `returning` to the query to get * the updated rows' columns (or any other expression) as the * return value: * @@ -544,11 +608,11 @@ export class UpdateQueryBuilder * * const result = await db * .updateTable('person') - * .set(({ selectFrom, ref, fn, bxp }) => ({ + * .set(({ selectFrom, ref, fn, eb }) => ({ * first_name: selectFrom('person').select('first_name').limit(1), * middle_name: ref('first_name'), - * age: bxp('age', '+', 1), - * last_name: sql`${'Ani'} || ${'ston'}`, + * age: eb('age', '+', 1), + * last_name: sql`${'Ani'} || ${'ston'}`, * })) * .where('id', '=', 1) * .executeTakeFirst() @@ -567,30 +631,53 @@ export class UpdateQueryBuilder * where "id" = $5 * ``` */ - set(update: UpdateObject): UpdateQueryBuilder - set( - update: UpdateObjectFactory + update: UpdateObjectExpression, ): UpdateQueryBuilder - set(update: UpdateExpression): UpdateQueryBuilder { + set>( + key: RE, + value: ValueExpression< + DB, + TB, + ExtractUpdateTypeFromReferenceExpression + >, + ): UpdateQueryBuilder + + set( + ...args: + | [UpdateObjectExpression] + | [ReferenceExpression, ValueExpression] + ): UpdateQueryBuilder { return new UpdateQueryBuilder({ ...this.#props, queryNode: UpdateQueryNode.cloneWithUpdates( this.#props.queryNode, - parseUpdateExpression(update) + parseUpdate(...args), ), }) } returning>( - selection: SelectArg + selections: ReadonlyArray, + ): UpdateQueryBuilder> + + returning>( + callback: CB, + ): UpdateQueryBuilder> + + returning>( + selection: SE, + ): UpdateQueryBuilder> + + returning>( + selection: SelectArg, ): UpdateQueryBuilder> { return new UpdateQueryBuilder({ ...this.#props, queryNode: QueryNode.cloneWithReturning( this.#props.queryNode, - parseSelectArg(selection) + parseSelectArg(selection), ), }) } @@ -600,11 +687,86 @@ export class UpdateQueryBuilder ...this.#props, queryNode: QueryNode.cloneWithReturning( this.#props.queryNode, - parseSelectAll() + parseSelectAll(), + ), + }) + } + + output>( + selections: readonly OE[] + ): UpdateQueryBuilder< + DB, + UT, + TB, + ReturningRow> + > + + output>( + callback: CB + ): UpdateQueryBuilder< + DB, + UT, + TB, + ReturningRow> + > + + output>( + selection: OE + ): UpdateQueryBuilder< + DB, + UT, + TB, + ReturningRow> + > + + output(args: any): any { + return new UpdateQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithOutput( + this.#props.queryNode, + parseSelectArg(args) + ), + }) + } + + outputAll( + table: OutputPrefix + ): UpdateQueryBuilder> { + return new UpdateQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithOutput( + this.#props.queryNode, + parseSelectAll(table) ), }) } + /** + * 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(): UpdateQueryBuilder { + return new UpdateQueryBuilder({ + ...this.#props, + queryNode: QueryNode.cloneWithoutReturning(this.#props.queryNode), + }) + } + /** * Simply calls the provided function passing `this` as the only argument. `$call` returns * what the provided function returns. @@ -632,13 +794,6 @@ export class UpdateQueryBuilder return func(this) } - /** - * @deprecated Use `$call` instead - */ - call(func: (qb: this) => T): T { - return this.$call(func) - } - /** * Call `func(this)` if `condition` is true. * @@ -677,7 +832,7 @@ export class UpdateQueryBuilder */ $if( condition: boolean, - func: (qb: this) => UpdateQueryBuilder + func: (qb: this) => UpdateQueryBuilder, ): O2 extends UpdateResult ? UpdateQueryBuilder : O2 extends O & infer E @@ -692,37 +847,16 @@ export class UpdateQueryBuilder }) as any } - /** - * @deprecated Use `$if` instead - */ - if( - condition: boolean, - func: (qb: this) => UpdateQueryBuilder - ): O2 extends UpdateResult - ? UpdateQueryBuilder - : O2 extends O & infer E - ? UpdateQueryBuilder> - : UpdateQueryBuilder> { - return this.$if(condition, func) - } - /** * Change the output type of the query. * - * You should only use this method as the last resort if the types - * don't support your use case. + * 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(): UpdateQueryBuilder { + $castTo(): UpdateQueryBuilder { return new UpdateQueryBuilder(this.#props) } - /** - * @deprecated Use `$castTo` instead. - */ - castTo(): UpdateQueryBuilder { - return this.$castTo() - } - /** * Narrows (parts of) the output type of the query. * @@ -820,15 +954,6 @@ export class UpdateQueryBuilder return new UpdateQueryBuilder(this.#props) as unknown as any } - /** - * @deprecated Use `$assertType` instead. - */ - assertType(): O extends T - ? UpdateQueryBuilder - : KyselyTypeError<`assertType() call failed: The type passed in is not equal to the output type of the query.`> { - return new UpdateQueryBuilder(this.#props) as unknown as any - } - /** * Returns a copy of this UpdateQueryBuilder instance with the given plugin installed. */ @@ -842,14 +967,14 @@ export class UpdateQueryBuilder toOperationNode(): UpdateQueryNode { return this.#props.executor.transformQuery( this.#props.queryNode, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery> { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -860,21 +985,28 @@ export class UpdateQueryBuilder */ async execute(): Promise[]> { const compiledQuery = this.compile() - const query = compiledQuery.query as UpdateQueryNode const result = await this.#props.executor.executeQuery( compiledQuery, - this.#props.queryId + this.#props.queryId, ) - if (this.#props.executor.adapter.supportsReturning && query.returning) { + const { adapter } = this.#props.executor + const query = compiledQuery.query as UpdateQueryNode + + if ( + (query.returning && adapter.supportsReturning) || + (query.output && adapter.supportsOutput) + ) { return result.rows as any } return [ new UpdateResult( // TODO: remove numUpdatedOrDeletedRows. - result.numAffectedRows ?? result.numUpdatedOrDeletedRows ?? BigInt(0) + // TODO: https://github.com/kysely-org/kysely/pull/431#discussion_r1172330899 + result.numAffectedRows ?? result.numUpdatedOrDeletedRows ?? BigInt(0), + result.numChangedRows, ) as any, ] } @@ -899,7 +1031,7 @@ export class UpdateQueryBuilder async executeTakeFirstOrThrow( errorConstructor: | NoResultErrorConstructor - | ((node: QueryNode) => Error) = NoResultError + | ((node: QueryNode) => Error) = NoResultError, ): Promise> { const result = await this.executeTakeFirst() @@ -920,7 +1052,7 @@ export class UpdateQueryBuilder const stream = this.#props.executor.stream( compiledQuery, chunkSize, - this.#props.queryId + this.#props.queryId, ) for await (const item of stream) { @@ -930,14 +1062,14 @@ export class UpdateQueryBuilder async explain = Record>( format?: ExplainFormat, - options?: Expression + options?: Expression, ): Promise { const builder = new UpdateQueryBuilder({ ...this.#props, queryNode: QueryNode.cloneWithExplain( this.#props.queryNode, format, - options + options, ), }) @@ -947,7 +1079,7 @@ export class UpdateQueryBuilder preventAwait( UpdateQueryBuilder, - "don't await UpdateQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`." + "don't await UpdateQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`.", ) export interface UpdateQueryBuilderProps { @@ -961,7 +1093,7 @@ export type UpdateQueryBuilderWithInnerJoin< UT extends keyof DB, TB extends keyof DB, O, - TE extends TableExpression + TE extends TableExpression, > = TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? InnerJoinedBuilder @@ -980,7 +1112,7 @@ type InnerJoinedBuilder< TB extends keyof DB, O, A extends string, - R + R, > = A extends keyof DB ? UpdateQueryBuilder, UT, TB | A, O> : // Much faster non-recursive solution for the simple case. @@ -995,7 +1127,7 @@ export type UpdateQueryBuilderWithLeftJoin< UT extends keyof DB, TB extends keyof DB, O, - TE extends TableExpression + TE extends TableExpression, > = TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? LeftJoinedBuilder @@ -1014,7 +1146,7 @@ type LeftJoinedBuilder< TB extends keyof DB, O, A extends keyof any, - R + R, > = A extends keyof DB ? UpdateQueryBuilder, UT, TB | A, O> : // Much faster non-recursive solution for the simple case. @@ -1033,7 +1165,7 @@ export type UpdateQueryBuilderWithRightJoin< UT extends keyof DB, TB extends keyof DB, O, - TE extends TableExpression + TE extends TableExpression, > = TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? RightJoinedBuilder @@ -1052,14 +1184,14 @@ type RightJoinedBuilder< TB extends keyof DB, O, A extends keyof any, - R + R, > = UpdateQueryBuilder, UT, TB | A, O> type RightJoinedDB< DB, TB extends keyof DB, A extends keyof any, - R + R, > = DrainOuterGeneric<{ [C in keyof DB | A]: C extends A ? R @@ -1075,7 +1207,7 @@ export type UpdateQueryBuilderWithFullJoin< UT extends keyof DB, TB extends keyof DB, O, - TE extends TableExpression + TE extends TableExpression, > = TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? OuterJoinedBuilder @@ -1094,14 +1226,14 @@ type OuterJoinedBuilder< TB extends keyof DB, O, A extends keyof any, - R + R, > = UpdateQueryBuilder, UT, TB | A, O> type OuterJoinedBuilderDB< DB, TB extends keyof DB, A extends keyof any, - R + R, > = DrainOuterGeneric<{ [C in keyof DB | A]: C extends A ? Nullable diff --git a/src/query-builder/update-result.ts b/src/query-builder/update-result.ts index 4492c3fed..4a35637f3 100644 --- a/src/query-builder/update-result.ts +++ b/src/query-builder/update-result.ts @@ -1,7 +1,9 @@ export class UpdateResult { readonly numUpdatedRows: bigint + readonly numChangedRows?: bigint - constructor(numUpdatedRows: bigint) { + constructor(numUpdatedRows: bigint, numChangedRows: bigint | undefined) { this.numUpdatedRows = numUpdatedRows + this.numChangedRows = numChangedRows } } diff --git a/src/query-builder/where-interface.ts b/src/query-builder/where-interface.ts index ef73f1492..2564a3194 100644 --- a/src/query-builder/where-interface.ts +++ b/src/query-builder/where-interface.ts @@ -1,13 +1,11 @@ -import { Expression } from '../expression/expression.js' import { ComparisonOperatorExpression, OperandValueExpressionOrList, } from '../parser/binary-operation-parser.js' import { ReferenceExpression } from '../parser/reference-parser.js' -import { ExistsExpression } from '../parser/unary-operation-parser.js' import { SqlBool } from '../util/type-utils.js' import { ExpressionBuilder } from '../expression/expression-builder.js' -import { WhereExpressionBuilder } from './deprecated-where-expression-builder.js' +import { ExpressionOrFactory } from '../parser/expression-parser.js' export interface WhereInterface { /** @@ -63,24 +61,53 @@ export interface WhereInterface { * select * from "person" where "id" in ($1, $2, $3) * ``` * - * + * * - * To combine conditions using `OR`, you can use the expression builder: + * You can use the `and` function to create a simple equality + * filter using an object * * ```ts * const persons = await db * .selectFrom('person') * .selectAll() - * .where(({ or, and, cmpr }) => or([ - * and([ - * cmpr('first_name', '=', 'Jennifer'), - * cmpr('last_name', '=', 'Aniston') - * ]), - * and([ - * cmpr('first_name', '=', 'Sylvester'), - * cmpr('last_name', '=', 'Stallone') - * ]) + * .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" + * ) + * ``` + * + * + * + * 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() * ``` * @@ -90,19 +117,23 @@ export interface WhereInterface { * select * * from "person" * where ( - * ("first_name" = $1 AND "last_name" = $2) - * OR - * ("first_name" = $3 AND "last_name" = $4) + * ("first_name" = $1 or "first_name" = $2) + * and + * ("last_name" = $3 or "last_name" = $4) * ) * ``` * - * + * * * 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') @@ -118,6 +149,23 @@ export interface WhereInterface { * query = query.where('last_name', '=', lastName) * } * + * if (under18 || over60) { + * // Conditional OR expressions can be added like this. + * query = query.where((eb) => { + * const ors: Expression[] = [] + * + * if (under18) { + * ors.push(eb('age', '<', 18)) + * } + * + * if (over60) { + * ors.push(eb('age', '>', 60)) + * } + * + * return eb.or(ors) + * }) + * } + * * const persons = await query.execute() * ``` * @@ -170,7 +218,7 @@ export interface WhereInterface { * select * from "person" where "id" in ($1, $2, $3) * ``` * - * + * * * For complex `where` expressions you can pass in a single callback and * use the `ExpressionBuilder` to build your expression: @@ -182,10 +230,10 @@ export interface WhereInterface { * const persons = await db * .selectFrom('person') * .selectAll('person') - * .where(({ cmpr, or, and, not, exists, selectFrom }) => and([ + * .where(({ eb, or, and, not, exists, selectFrom }) => and([ * or([ - * cmpr('first_name', '=', firstName), - * cmpr('age', '<', maxAge) + * eb('first_name', '=', firstName), + * eb('age', '<', maxAge) * ]), * not(exists( * selectFrom('pet') @@ -222,7 +270,7 @@ export interface WhereInterface { * .selectFrom('person') * .selectAll() * .where( - * sql`coalesce(first_name, last_name)`, + * sql`coalesce(first_name, last_name)`, * 'like', * '%' + name + '%', * ) @@ -259,15 +307,18 @@ export interface WhereInterface { * .execute() * ``` */ - where>( + where< + RE extends ReferenceExpression, + VE extends OperandValueExpressionOrList, + >( lhs: RE, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: VE, ): WhereInterface - where(factory: WhereExpressionFactory): WhereInterface - - where(expression: Expression): WhereInterface + where>( + expression: E, + ): WhereInterface /** * Adds a `where` clause where both sides of the operator are references @@ -320,60 +371,15 @@ export interface WhereInterface { * ) as "pet_name" * from "person" */ - whereRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): WhereInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere>( - lhs: RE, + whereRef< + LRE extends ReferenceExpression, + RRE extends ReferenceExpression, + >( + lhs: LRE, op: ComparisonOperatorExpression, - rhs: OperandValueExpressionOrList + rhs: RRE, ): WhereInterface - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere(factory: WhereExpressionFactory): WhereInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhere(expression: Expression): WhereInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhereRef( - lhs: ReferenceExpression, - op: ComparisonOperatorExpression, - rhs: ReferenceExpression - ): WhereInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - whereExists(arg: ExistsExpression): WhereInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - whereNotExists(arg: ExistsExpression): WhereInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhereExists(arg: ExistsExpression): WhereInterface - - /** - * @deprecated Follow [these](https://github.com/koskimas/kysely/releases/tag/0.24.0) instructions to migrate - */ - orWhereNotExists(arg: ExistsExpression): WhereInterface - /** * Clears all where expressions from the query. * @@ -394,7 +400,3 @@ export interface WhereInterface { */ clearWhere(): WhereInterface } - -export type WhereExpressionFactory = ( - eb: WhereExpressionBuilder -) => Expression | WhereExpressionBuilder diff --git a/src/query-compiler/default-query-compiler.ts b/src/query-compiler/default-query-compiler.ts index c6ba29b6c..321f41bb0 100644 --- a/src/query-compiler/default-query-compiler.ts +++ b/src/query-compiler/default-query-compiler.ts @@ -58,7 +58,10 @@ import { RootOperationNode, QueryCompiler } from './query-compiler.js' import { HavingNode } from '../operation-node/having-node.js' import { CreateSchemaNode } from '../operation-node/create-schema-node.js' import { DropSchemaNode } from '../operation-node/drop-schema-node.js' -import { AlterTableNode } from '../operation-node/alter-table-node.js' +import { + AlterTableColumnAlterationNode, + AlterTableNode, +} from '../operation-node/alter-table-node.js' import { DropColumnNode } from '../operation-node/drop-column-node.js' import { RenameColumnNode } from '../operation-node/rename-column-node.js' import { AlterColumnNode } from '../operation-node/alter-column-node.js' @@ -96,6 +99,18 @@ import { UsingNode } from '../operation-node/using-node.js' import { FunctionNode } from '../operation-node/function-node.js' import { CaseNode } from '../operation-node/case-node.js' import { WhenNode } from '../operation-node/when-node.js' +import { JSONReferenceNode } from '../operation-node/json-reference-node.js' +import { JSONPathNode } from '../operation-node/json-path-node.js' +import { JSONPathLegNode } from '../operation-node/json-path-leg-node.js' +import { JSONOperatorChainNode } from '../operation-node/json-operator-chain-node.js' +import { TupleNode } from '../operation-node/tuple-node.js' +import { MergeQueryNode } from '../operation-node/merge-query-node.js' +import { MatchedNode } from '../operation-node/matched-node.js' +import { AddIndexNode } from '../operation-node/add-index-node.js' +import { CastNode } from '../operation-node/cast-node.js' +import { FetchNode } from '../operation-node/fetch-node.js' +import { TopNode } from '../operation-node/top-node.js' +import { OutputNode } from '../operation-node/output-node.js' export class DefaultQueryCompiler extends OperationNodeVisitor @@ -128,7 +143,9 @@ export class DefaultQueryCompiler protected override visitSelectQuery(node: SelectQueryNode): void { const wrapInParens = this.parentNode !== undefined && + !ParensNode.is(this.parentNode) && !InsertQueryNode.is(this.parentNode) && + !CreateTableNode.is(this.parentNode) && !CreateViewNode.is(this.parentNode) && !SetOperationNode.is(this.parentNode) @@ -146,24 +163,32 @@ export class DefaultQueryCompiler this.append(' ') } - this.append('select ') + this.append('select') if (node.distinctOn) { - this.compileDistinctOn(node.distinctOn) this.append(' ') + this.compileDistinctOn(node.distinctOn) } - if (node.frontModifiers && node.frontModifiers.length > 0) { + if (node.frontModifiers?.length) { + this.append(' ') this.compileList(node.frontModifiers, ' ') + } + + if (node.top) { this.append(' ') + this.visitNode(node.top) } if (node.selections) { - this.compileList(node.selections) this.append(' ') + this.compileList(node.selections) } - this.visitNode(node.from) + if (node.from) { + this.append(' ') + this.visitNode(node.from) + } if (node.joins) { this.append(' ') @@ -205,9 +230,14 @@ export class DefaultQueryCompiler this.visitNode(node.offset) } - if (node.endModifiers && node.endModifiers.length > 0) { + if (node.fetch) { this.append(' ') - this.compileList(node.endModifiers, ' ') + this.visitNode(node.fetch) + } + + if (node.endModifiers?.length) { + this.append(' ') + this.compileList(this.sortSelectModifiers([...node.endModifiers]), ' ') } if (wrapInParens) { @@ -236,7 +266,7 @@ export class DefaultQueryCompiler protected compileList( nodes: ReadonlyArray, - separator = ', ' + separator = ', ', ): void { const lastIndex = nodes.length - 1 @@ -260,14 +290,15 @@ export class DefaultQueryCompiler } protected override visitInsertQuery(node: InsertQueryNode): void { - const isSubQuery = this.nodeStack.find(QueryNode.is) !== node + const rootQueryNode = this.nodeStack.find(QueryNode.is)! + const isSubQuery = rootQueryNode !== node if (!isSubQuery && node.explain) { this.visitNode(node.explain) this.append(' ') } - if (isSubQuery) { + if (isSubQuery && !MergeQueryNode.is(rootQueryNode)) { this.append('(') } @@ -282,8 +313,15 @@ export class DefaultQueryCompiler this.append(' ignore') } - this.append(' into ') - this.visitNode(node.into) + if (node.top) { + this.append(' ') + this.visitNode(node.top) + } + + if (node.into) { + this.append(' into ') + this.visitNode(node.into) + } if (node.columns) { this.append(' (') @@ -291,11 +329,21 @@ export class DefaultQueryCompiler this.append(')') } + if (node.output) { + this.append(' ') + this.visitNode(node.output) + } + if (node.values) { this.append(' ') this.visitNode(node.values) } + if (node.defaultValues) { + this.append(' ') + this.append('default values') + } + if (node.onConflict) { this.append(' ') this.visitNode(node.onConflict) @@ -311,7 +359,7 @@ export class DefaultQueryCompiler this.visitNode(node.returning) } - if (isSubQuery) { + if (isSubQuery && !MergeQueryNode.is(rootQueryNode)) { this.append(')') } } @@ -339,8 +387,19 @@ export class DefaultQueryCompiler } this.append('delete ') + + if (node.top) { + this.visitNode(node.top) + this.append(' ') + } + this.visitNode(node.from) + if (node.output) { + this.append(' ') + this.visitNode(node.output) + } + if (node.using) { this.append(' ') this.visitNode(node.using) @@ -388,8 +447,11 @@ export class DefaultQueryCompiler } protected override visitReference(node: ReferenceNode): void { - this.visitNode(node.table) - this.append('.') + if (node.table) { + this.visitNode(node.table) + this.append('.') + } + this.visitNode(node.column) } @@ -406,7 +468,7 @@ export class DefaultQueryCompiler protected compileUnwrappedIdentifier(node: IdentifierNode): void { if (!isString(node.name)) { throw new Error( - 'a non-string identifier was passed to compileUnwrappedIdentifier.' + 'a non-string identifier was passed to compileUnwrappedIdentifier.', ) } @@ -439,8 +501,14 @@ export class DefaultQueryCompiler this.append(')') } + protected override visitTuple(node: TupleNode): void { + this.append('(') + this.compileList(node.values) + this.append(')') + } + protected override visitPrimitiveValueList( - node: PrimitiveValueListNode + node: PrimitiveValueListNode, ): void { this.append('(') @@ -499,7 +567,7 @@ export class DefaultQueryCompiler } protected override visitSchemableIdentifier( - node: SchemableIdentifierNode + node: SchemableIdentifierNode, ): void { if (node.schema) { this.visitNode(node.schema) @@ -528,22 +596,32 @@ export class DefaultQueryCompiler } this.visitNode(node.table) - this.append(' (') - this.compileList([...node.columns, ...(node.constraints ?? [])]) - this.append(')') - if (node.onCommit) { - this.append(' on commit ') - this.append(node.onCommit) - } + if (node.selectQuery) { + this.append(' as ') + this.visitNode(node.selectQuery) + } else { + this.append(' (') + this.compileList([...node.columns, ...(node.constraints ?? [])]) + this.append(')') - if (node.endModifiers && node.endModifiers.length > 0) { - this.append(' ') - this.compileList(node.endModifiers, ' ') + if (node.onCommit) { + this.append(' on commit ') + this.append(node.onCommit) + } + + if (node.endModifiers && node.endModifiers.length > 0) { + this.append(' ') + this.compileList(node.endModifiers, ' ') + } } } protected override visitColumnDefinition(node: ColumnDefinitionNode): void { + if (node.ifNotExists) { + this.append('if not exists ') + } + this.visitNode(node.column) this.append(' ') @@ -563,6 +641,10 @@ export class DefaultQueryCompiler this.visitNode(node.generated) } + if (node.identity) { + this.append(' identity') + } + if (node.defaultTo) { this.append(' ') this.visitNode(node.defaultTo) @@ -576,6 +658,10 @@ export class DefaultQueryCompiler this.append(' unique') } + if (node.nullsNotDistinct) { + this.append(' nulls not distinct') + } + if (node.primaryKey) { this.append(' primary key') } @@ -665,14 +751,15 @@ export class DefaultQueryCompiler } protected override visitUpdateQuery(node: UpdateQueryNode): void { - const isSubQuery = this.nodeStack.find(QueryNode.is) !== node + const rootQueryNode = this.nodeStack.find(QueryNode.is)! + const isSubQuery = rootQueryNode !== node if (!isSubQuery && node.explain) { this.visitNode(node.explain) this.append(' ') } - if (isSubQuery) { + if (isSubQuery && !MergeQueryNode.is(rootQueryNode)) { this.append('(') } @@ -682,13 +769,28 @@ export class DefaultQueryCompiler } this.append('update ') - this.visitNode(node.table) - this.append(' set ') + + if (node.top) { + this.visitNode(node.top) + this.append(' ') + } + + if (node.table) { + this.visitNode(node.table) + this.append(' ') + } + + this.append('set ') if (node.updates) { this.compileList(node.updates) } + if (node.output) { + this.append(' ') + this.visitNode(node.output) + } + if (node.from) { this.append(' ') this.visitNode(node.from) @@ -704,12 +806,17 @@ export class DefaultQueryCompiler this.visitNode(node.where) } + if (node.limit) { + this.append(' ') + this.visitNode(node.limit) + } + if (node.returning) { this.append(' ') this.visitNode(node.returning) } - if (isSubQuery) { + if (isSubQuery && !MergeQueryNode.is(rootQueryNode)) { this.append(')') } } @@ -800,6 +907,10 @@ export class DefaultQueryCompiler this.append(')') } + if (node.nullsNotDistinct) { + this.append(' nulls not distinct') + } + if (node.where) { this.append(' ') this.visitNode(node.where) @@ -850,7 +961,7 @@ export class DefaultQueryCompiler } protected override visitPrimaryKeyConstraint( - node: PrimaryKeyConstraintNode + node: PrimaryKeyConstraintNode, ): void { if (node.name) { this.append('constraint ') @@ -870,7 +981,13 @@ export class DefaultQueryCompiler this.append(' ') } - this.append('unique (') + this.append('unique') + + if (node.nullsNotDistinct) { + this.append(' nulls not distinct') + } + + this.append(' (') this.compileList(node.columns) this.append(')') } @@ -888,7 +1005,7 @@ export class DefaultQueryCompiler } protected override visitForeignKeyConstraint( - node: ForeignKeyConstraintNode + node: ForeignKeyConstraintNode, ): void { if (node.name) { this.append('constraint ') @@ -927,15 +1044,24 @@ export class DefaultQueryCompiler } protected override visitCommonTableExpression( - node: CommonTableExpressionNode + node: CommonTableExpressionNode, ): void { this.visitNode(node.name) this.append(' as ') + + if (isBoolean(node.materialized)) { + if (!node.materialized) { + this.append('not ') + } + + this.append('materialized ') + } + this.visitNode(node.expression) } protected override visitCommonTableExpressionName( - node: CommonTableExpressionNameNode + node: CommonTableExpressionNameNode, ): void { this.visitNode(node.table) @@ -970,7 +1096,15 @@ export class DefaultQueryCompiler } if (node.columnAlterations) { - this.compileList(node.columnAlterations) + this.compileColumnAlterations(node.columnAlterations) + } + + if (node.addIndex) { + this.visitNode(node.addIndex) + } + + if (node.dropIndex) { + this.visitNode(node.dropIndex) } } @@ -997,7 +1131,10 @@ export class DefaultQueryCompiler this.append(' ') if (node.dataType) { - this.append('type ') + if (this.announcesNewColumnDataType()) { + this.append('type ') + } + this.visitNode(node.dataType) if (node.dataTypeExpression) { @@ -1156,6 +1293,11 @@ export class DefaultQueryCompiler } else { this.append(SELECT_MODIFIER_SQL[node.modifier!]) } + + if (node.of) { + this.append(' of ') + this.compileList(node.of, ', ') + } } protected override visitCreateType(node: CreateTypeNode): void { @@ -1327,6 +1469,143 @@ export class DefaultQueryCompiler } } + protected override visitJSONReference(node: JSONReferenceNode): void { + this.visitNode(node.reference) + this.visitNode(node.traversal) + } + + protected override visitJSONPath(node: JSONPathNode): void { + if (node.inOperator) { + this.visitNode(node.inOperator) + } + + this.append("'$") + + for (const pathLeg of node.pathLegs) { + this.visitNode(pathLeg) + } + + this.append("'") + } + + protected override visitJSONPathLeg(node: JSONPathLegNode): void { + const isArrayLocation = node.type === 'ArrayLocation' + + this.append(isArrayLocation ? '[' : '.') + + this.append(String(node.value)) + + if (isArrayLocation) { + this.append(']') + } + } + + protected override visitJSONOperatorChain(node: JSONOperatorChainNode): void { + for (let i = 0, len = node.values.length; i < len; i++) { + if (i === len - 1) { + this.visitNode(node.operator) + } else { + this.append('->') + } + + this.visitNode(node.values[i]) + } + } + + protected override visitMergeQuery(node: MergeQueryNode): void { + if (node.with) { + this.visitNode(node.with) + this.append(' ') + } + + this.append('merge ') + + if (node.top) { + this.visitNode(node.top) + this.append(' ') + } + + this.append('into ') + this.visitNode(node.into) + + if (node.using) { + this.append(' ') + this.visitNode(node.using) + } + + if (node.whens) { + this.append(' ') + this.compileList(node.whens, ' ') + } + + if (node.output) { + this.append(' ') + this.visitNode(node.output) + } + } + + protected override visitMatched(node: MatchedNode): void { + if (node.not) { + this.append('not ') + } + + this.append('matched') + + if (node.bySource) { + this.append(' by source') + } + } + + protected override visitAddIndex(node: AddIndexNode): void { + this.append('add ') + + if (node.unique) { + this.append('unique ') + } + + this.append('index ') + + this.visitNode(node.name) + + if (node.columns) { + this.append(' (') + this.compileList(node.columns) + this.append(')') + } + + if (node.using) { + this.append(' using ') + this.visitNode(node.using) + } + } + + protected override visitCast(node: CastNode): void { + this.append('cast(') + this.visitNode(node.expression) + this.append(' as ') + this.visitNode(node.dataType) + this.append(')') + } + + protected override visitFetch(node: FetchNode): void { + this.append('fetch next ') + this.visitNode(node.rowCount) + this.append(` rows ${node.modifier}`) + } + + protected override visitOutput(node: OutputNode): void { + this.append('output ') + this.compileList(node.selections) + } + + protected override visitTop(node: TopNode): void { + this.append(`top(${node.expression})`) + + if (node.modifiers) { + this.append(` ${node.modifiers}`) + } + } + protected append(str: string): void { this.#sql += str } @@ -1401,6 +1680,33 @@ export class DefaultQueryCompiler throw new Error(`invalid immediate value ${value}`) } } + + protected sortSelectModifiers( + arr: SelectModifierNode[], + ): ReadonlyArray { + arr.sort((left, right) => + left.modifier && right.modifier + ? SELECT_MODIFIER_PRIORITY[left.modifier] - + SELECT_MODIFIER_PRIORITY[right.modifier] + : 1, + ) + + return freeze(arr) + } + + protected compileColumnAlterations( + columnAlterations: readonly AlterTableColumnAlterationNode[], + ) { + this.compileList(columnAlterations) + } + + /** + * controls whether the dialect adds a "type" keyword before a column's new data + * type in an ALTER TABLE statement. + */ + protected announcesNewColumnDataType(): boolean { + return true + } } const SELECT_MODIFIER_SQL: Readonly> = freeze({ @@ -1413,6 +1719,17 @@ const SELECT_MODIFIER_SQL: Readonly> = freeze({ Distinct: 'distinct', }) +const SELECT_MODIFIER_PRIORITY: Readonly> = + freeze({ + ForKeyShare: 1, + ForNoKeyUpdate: 1, + ForUpdate: 1, + ForShare: 1, + NoWait: 2, + SkipLocked: 2, + Distinct: 0, + }) + const JOIN_TYPE_SQL: Readonly> = freeze({ InnerJoin: 'inner join', LeftJoin: 'left join', @@ -1420,4 +1737,5 @@ const JOIN_TYPE_SQL: Readonly> = freeze({ FullJoin: 'full join', LateralInnerJoin: 'inner join lateral', LateralLeftJoin: 'left join lateral', + Using: 'using', }) diff --git a/src/query-compiler/query-compiler.ts b/src/query-compiler/query-compiler.ts index 9aa5e90c0..ec3ed9a63 100644 --- a/src/query-compiler/query-compiler.ts +++ b/src/query-compiler/query-compiler.ts @@ -9,6 +9,7 @@ import { DropSchemaNode } from '../operation-node/drop-schema-node.js' import { DropTableNode } from '../operation-node/drop-table-node.js' import { DropTypeNode } from '../operation-node/drop-type-node.js' import { DropViewNode } from '../operation-node/drop-view-node.js' +import { MergeQueryNode } from '../operation-node/merge-query-node.js' import { QueryNode } from '../operation-node/query-node.js' import { RawNode } from '../operation-node/raw-node.js' import { CompiledQuery } from './compiled-query.js' @@ -27,6 +28,7 @@ export type RootOperationNode = | RawNode | CreateTypeNode | DropTypeNode + | MergeQueryNode /** * a `QueryCompiler` compiles a query expressed as a tree of `OperationNodes` into SQL. diff --git a/src/query-creator.ts b/src/query-creator.ts index 12f9f682d..dfdca0cb1 100644 --- a/src/query-creator.ts +++ b/src/query-creator.ts @@ -1,4 +1,7 @@ -import { SelectQueryBuilder } from './query-builder/select-query-builder.js' +import { + SelectQueryBuilder, + createSelectQueryBuilder, +} from './query-builder/select-query-builder.js' import { InsertQueryBuilder } from './query-builder/insert-query-builder.js' import { DeleteQueryBuilder } from './query-builder/delete-query-builder.js' import { UpdateQueryBuilder } from './query-builder/update-query-builder.js' @@ -19,13 +22,15 @@ import { ExtractTableAlias, AnyAliasedTable, PickTableWithAlias, + SimpleTableReference, + parseAliasedTable, } from './parser/table-parser.js' import { QueryExecutor } from './query-executor/query-executor.js' import { CommonTableExpression, - parseCommonTableExpression, QueryCreatorWithCommonTableExpression, RecursiveCommonTableExpression, + parseCommonTableExpression, } from './parser/with-parser.js' import { WithNode } from './operation-node/with-node.js' import { createQueryId } from './util/query-id.js' @@ -35,6 +40,18 @@ import { InsertResult } from './query-builder/insert-result.js' import { DeleteResult } from './query-builder/delete-result.js' import { UpdateResult } from './query-builder/update-result.js' import { KyselyPlugin } from './plugin/kysely-plugin.js' +import { CTEBuilderCallback } from './query-builder/cte-builder.js' +import { + CallbackSelection, + SelectArg, + SelectCallback, + SelectExpression, + Selection, + parseSelectArg, +} from './parser/select-parser.js' +import { MergeQueryBuilder } from './query-builder/merge-query-builder.js' +import { MergeQueryNode } from './operation-node/merge-query-node.js' +import { MergeResult } from './query-builder/merge-result.js' export class QueryCreator { readonly #props: QueryCreatorProps @@ -151,36 +168,108 @@ export class QueryCreator { * ``` */ selectFrom( - from: TE[] + from: TE[], ): SelectQueryBuilder, {}> selectFrom>( - from: TE[] + from: TE[], ): SelectQueryBuilder, FromTables, {}> selectFrom( - from: TE + from: TE, ): SelectQueryBuilder, {}> selectFrom>( - from: TE + from: TE, ): SelectQueryBuilder< DB & PickTableWithAlias, - ExtractTableAlias, + ExtractTableAlias, TE>, {} > selectFrom>( - from: TE + from: TE, ): SelectQueryBuilder, FromTables, {}> selectFrom(from: TableExpressionOrList): any { - return new SelectQueryBuilder({ + return createSelectQueryBuilder({ queryId: createQueryId(), executor: this.#props.executor, - queryNode: SelectQueryNode.create( + queryNode: SelectQueryNode.createFrom( parseTableExpressionOrList(from), - this.#props.withNode + this.#props.withNode, + ), + }) + } + + /** + * Creates a `select` query builder without a `from` clause. + * + * If you want to create a `select from` query, use the `selectFrom` method instead. + * This one can be used to create a plain `select` statement without a `from` clause. + * + * This method accepts the same inputs as {@link SelectQueryBuilder.select}. See its + * documentation for more examples. + * + * ### Examples + * + * ```ts + * const result = db.selectNoFrom((eb) => [ + * eb.selectFrom('person') + * .select('id') + * .where('first_name', '=', 'Jennifer') + * .limit(1) + * .as('jennifer_id'), + * + * eb.selectFrom('pet') + * .select('id') + * .where('name', '=', 'Doggo') + * .limit(1) + * .as('doggo_id') + * ]) + * .executeTakeFirstOrThrow() + * + * console.log(result.jennifer_id) + * console.log(result.doggo_id) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * select ( + * select "id" + * from "person" + * where "first_name" = $1 + * limit $2 + * ) as "jennifer_id", ( + * select "id" + * from "pet" + * where "name" = $3 + * limit $4 + * ) as "doggo_id" + * ``` + */ + selectNoFrom>( + selections: ReadonlyArray, + ): SelectQueryBuilder> + + selectNoFrom>( + callback: CB, + ): SelectQueryBuilder> + + selectNoFrom>( + selection: SE, + ): SelectQueryBuilder> + + selectNoFrom>( + selection: SelectArg, + ): SelectQueryBuilder> { + return createSelectQueryBuilder({ + queryId: createQueryId(), + executor: this.#props.executor, + queryNode: SelectQueryNode.cloneWithSelections( + SelectQueryNode.create(this.#props.withNode), + parseSelectArg(selection as any), ), }) } @@ -224,14 +313,14 @@ export class QueryCreator { * ``` */ insertInto( - table: T + table: T, ): InsertQueryBuilder { return new InsertQueryBuilder({ queryId: createQueryId(), executor: this.#props.executor, queryNode: InsertQueryNode.create( parseTable(table), - this.#props.withNode + this.#props.withNode, ), }) } @@ -263,7 +352,7 @@ export class QueryCreator { * ``` */ replaceInto( - table: T + table: T, ): InsertQueryBuilder { return new InsertQueryBuilder({ queryId: createQueryId(), @@ -271,7 +360,7 @@ export class QueryCreator { queryNode: InsertQueryNode.create( parseTable(table), this.#props.withNode, - true + true, ), }) } @@ -326,19 +415,19 @@ export class QueryCreator { * ``` */ deleteFrom( - from: TR[] + from: TR[], ): DeleteQueryBuilder, DeleteResult> deleteFrom>( - tables: TR[] + tables: TR[], ): DeleteQueryBuilder, FromTables, DeleteResult> deleteFrom( - from: TR + from: TR, ): DeleteQueryBuilder, DeleteResult> deleteFrom>( - table: TR + table: TR, ): DeleteQueryBuilder, FromTables, DeleteResult> deleteFrom(tables: TableReferenceOrList): any { @@ -347,7 +436,7 @@ export class QueryCreator { executor: this.#props.executor, queryNode: DeleteQueryNode.create( parseTableExpressionOrList(tables), - this.#props.withNode + this.#props.withNode, ), }) } @@ -376,7 +465,7 @@ export class QueryCreator { * ``` */ updateTable( - table: TR + table: TR, ): UpdateQueryBuilder< DB, ExtractTableAlias, @@ -385,16 +474,16 @@ export class QueryCreator { > updateTable>( - table: TR + table: TR, ): UpdateQueryBuilder< DB & PickTableWithAlias, - ExtractTableAlias, - ExtractTableAlias, + ExtractTableAlias, TR>, + ExtractTableAlias, TR>, UpdateResult > updateTable>( - table: TR + table: TR, ): UpdateQueryBuilder< From, FromTables, @@ -408,7 +497,64 @@ export class QueryCreator { executor: this.#props.executor, queryNode: UpdateQueryNode.create( parseTableExpression(table), - this.#props.withNode + this.#props.withNode, + ), + }) + } + + /** + * Creates a merge query. + * + * The return value of the query is a {@link MergeResult}. + * + * See the {@link MergeQueryBuilder.using} method for examples on how to specify + * the other table. + * + * ### Examples + * + * ```ts + * const result = await db + * .mergeInto('person') + * .using('pet', 'pet.owner_id', 'person.id') + * .whenMatched((and) => and('has_pets', '!=', 'Y')) + * .thenUpdateSet({ has_pets: 'Y' }) + * .whenNotMatched() + * .thenDoNothing() + * .executeTakeFirstOrThrow() + * + * console.log(result.numChangedRows) + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * merge into "person" + * using "pet" on "pet"."owner_id" = "person"."id" + * when matched and "has_pets" != $1 then + * update set "has_pets" = $2 + * when not matched then + * do nothing + * ``` + */ + mergeInto( + targetTable: TR, + ): MergeQueryBuilder + + mergeInto>( + targetTable: TR, + ): MergeQueryBuilder< + DB & PickTableWithAlias, + ExtractTableAlias, TR>, + MergeResult + > + + mergeInto>(targetTable: TR): any { + return new MergeQueryBuilder({ + queryId: createQueryId(), + executor: this.#props.executor, + queryNode: MergeQueryNode.create( + parseAliasedTable(targetTable), + this.#props.withNode, ), }) } @@ -418,24 +564,77 @@ export class QueryCreator { * * ### Examples * + * + * + * Common table expressions (CTE) are a great way to modularize complex queries. + * Essentially they allow you to run multiple separate queries within a + * single roundtrip to the DB. + * + * Since CTEs are a part of the main query, query optimizers inside DB + * engines are able to optimize the overall query. For example, postgres + * is able to inline the CTEs inside the using queries if it decides it's + * faster. + * * ```ts - * await db + * const result = await db + * // Create a CTE called `jennifers` that selects all + * // persons named 'Jennifer'. * .with('jennifers', (db) => db * .selectFrom('person') * .where('first_name', '=', 'Jennifer') * .select(['id', 'age']) * ) + * // Select all rows from the `jennifers` CTE and + * // further filter it. * .with('adult_jennifers', (db) => db * .selectFrom('jennifers') * .where('age', '>', 18) * .select(['id', 'age']) * ) + * // Finally select all adult jennifers that are + * // also younger than 60. * .selectFrom('adult_jennifers') * .where('age', '<', 60) * .selectAll() * .execute() * ``` * + * + * + * Some databases like postgres also allow you to run other queries than selects + * in CTEs. On these databases CTEs are extremely powerful: + * + * ```ts + * const result = await db + * .with('new_person', (db) => db + * .insertInto('person') + * .values({ + * first_name: 'Jennifer', + * age: 35, + * }) + * .returning('id') + * ) + * .with('new_pet', (db) => db + * .insertInto('pet') + * .values({ + * name: 'Doggo', + * species: 'dog', + * is_favorite: true, + * // Use the id of the person we just inserted. + * owner_id: db + * .selectFrom('new_person') + * .select('id') + * }) + * .returning('id') + * ) + * .selectFrom(['new_person', 'new_pet']) + * .select([ + * 'new_person.id as person_id', + * 'new_pet.id as pet_id' + * ]) + * .execute() + * ``` + * * The CTE name can optionally specify column names in addition to * a name. In that case Kysely requires the expression to retun * rows with the same columns. @@ -453,12 +652,29 @@ export class QueryCreator { * .selectAll() * .execute() * ``` + * + * The first argument can also be a callback. The callback is passed + * a `CTEBuilder` instance that can be used to configure the CTE: + * + * ```ts + * await db + * .with( + * (cte) => cte('jennifers').materialized(), + * (db) => db + * .selectFrom('person') + * .where('first_name', '=', 'Jennifer') + * .select(['id', 'age']) + * ) + * .selectFrom('jennifers') + * .selectAll() + * .execute() + * ``` */ with>( - name: N, - expression: E + nameOrBuilder: N | CTEBuilderCallback, + expression: E, ): QueryCreatorWithCommonTableExpression { - const cte = parseCommonTableExpression(name, expression) + const cte = parseCommonTableExpression(nameOrBuilder, expression as any) return new QueryCreator({ ...this.#props, @@ -471,13 +687,21 @@ export class QueryCreator { /** * Creates a recursive `with` query (Common Table Expression). * + * Note that recursiveness is a property of the whole `with` statement. + * You cannot have recursive and non-recursive CTEs in a same `with` statement. + * Therefore the recursiveness is determined by the **first** `with` or + * `withRecusive` call you make. + * * See the {@link with} method for examples and more documentation. */ withRecursive< N extends string, - E extends RecursiveCommonTableExpression - >(name: N, expression: E): QueryCreatorWithCommonTableExpression { - const cte = parseCommonTableExpression(name, expression) + E extends RecursiveCommonTableExpression, + >( + nameOrBuilder: N | CTEBuilderCallback, + expression: E, + ): QueryCreatorWithCommonTableExpression { + const cte = parseCommonTableExpression(nameOrBuilder, expression) return new QueryCreator({ ...this.#props, @@ -558,7 +782,7 @@ export class QueryCreator { return new QueryCreator({ ...this.#props, executor: this.#props.executor.withPluginAtFront( - new WithSchemaPlugin(schema) + new WithSchemaPlugin(schema), ), }) } diff --git a/src/query-executor/default-query-executor.ts b/src/query-executor/default-query-executor.ts index adb7a7f62..65b65c5e3 100644 --- a/src/query-executor/default-query-executor.ts +++ b/src/query-executor/default-query-executor.ts @@ -18,7 +18,7 @@ export class DefaultQueryExecutor extends QueryExecutorBase { compiler: QueryCompiler, adapter: DialectAdapter, connectionProvider: ConnectionProvider, - plugins: KyselyPlugin[] = [] + plugins: KyselyPlugin[] = [], ) { super(plugins) @@ -36,7 +36,7 @@ export class DefaultQueryExecutor extends QueryExecutorBase { } provideConnection( - consumer: (connection: DatabaseConnection) => Promise + consumer: (connection: DatabaseConnection) => Promise, ): Promise { return this.#connectionProvider.provideConnection(consumer) } @@ -46,7 +46,7 @@ export class DefaultQueryExecutor extends QueryExecutorBase { this.#compiler, this.#adapter, this.#connectionProvider, - [...this.plugins, ...plugins] + [...this.plugins, ...plugins], ) } @@ -55,7 +55,7 @@ export class DefaultQueryExecutor extends QueryExecutorBase { this.#compiler, this.#adapter, this.#connectionProvider, - [...this.plugins, plugin] + [...this.plugins, plugin], ) } @@ -64,18 +64,18 @@ export class DefaultQueryExecutor extends QueryExecutorBase { this.#compiler, this.#adapter, this.#connectionProvider, - [plugin, ...this.plugins] + [plugin, ...this.plugins], ) } withConnectionProvider( - connectionProvider: ConnectionProvider + connectionProvider: ConnectionProvider, ): DefaultQueryExecutor { return new DefaultQueryExecutor( this.#compiler, this.#adapter, connectionProvider, - [...this.plugins] + [...this.plugins], ) } @@ -84,7 +84,7 @@ export class DefaultQueryExecutor extends QueryExecutorBase { this.#compiler, this.#adapter, this.#connectionProvider, - [] + [], ) } } diff --git a/src/query-executor/query-executor-base.ts b/src/query-executor/query-executor-base.ts index e51fed3a9..8bc6d3db4 100644 --- a/src/query-executor/query-executor-base.ts +++ b/src/query-executor/query-executor-base.ts @@ -43,7 +43,7 @@ export abstract class QueryExecutorBase implements QueryExecutor { `of the same kind that was given to it.`, `The plugin was given a ${node.kind}`, `but it returned a ${transformedNode.kind}`, - ].join(' ') + ].join(' '), ) } } @@ -53,20 +53,19 @@ export abstract class QueryExecutorBase implements QueryExecutor { abstract compileQuery( node: RootOperationNode, - queryId: QueryId + queryId: QueryId, ): CompiledQuery abstract provideConnection( - consumer: (connection: DatabaseConnection) => Promise + consumer: (connection: DatabaseConnection) => Promise, ): Promise async executeQuery( compiledQuery: CompiledQuery, - queryId: QueryId + queryId: QueryId, ): Promise> { return await this.provideConnection(async (connection) => { const result = await connection.executeQuery(compiledQuery) - const transformedResult = await this.#transformResult(result, queryId) // TODO: remove. @@ -79,7 +78,7 @@ export abstract class QueryExecutorBase implements QueryExecutor { async *stream( compiledQuery: CompiledQuery, chunkSize: number, - queryId: QueryId + queryId: QueryId, ): AsyncIterableIterator> { const connectionDefer = new Deferred() const connectionReleaseDefer = new Deferred() @@ -96,7 +95,7 @@ export abstract class QueryExecutorBase implements QueryExecutor { try { for await (const result of connection.streamQuery( compiledQuery, - chunkSize + chunkSize, )) { yield await this.#transformResult(result, queryId) } @@ -106,7 +105,7 @@ export abstract class QueryExecutorBase implements QueryExecutor { } abstract withConnectionProvider( - connectionProvider: ConnectionProvider + connectionProvider: ConnectionProvider, ): QueryExecutorBase abstract withPlugin(plugin: KyselyPlugin): QueryExecutorBase @@ -116,7 +115,7 @@ export abstract class QueryExecutorBase implements QueryExecutor { async #transformResult( result: QueryResult, - queryId: QueryId + queryId: QueryId, ): Promise> { for (const plugin of this.#plugins) { result = await plugin.transformResult({ result, queryId }) @@ -129,7 +128,7 @@ export abstract class QueryExecutorBase implements QueryExecutor { // TODO: remove. function warnOfOutdatedDriverOrPlugins( result: QueryResult, - transformedResult: QueryResult + transformedResult: QueryResult, ): void { const { numAffectedRows } = result @@ -143,6 +142,6 @@ function warnOfOutdatedDriverOrPlugins( } logOnce( - 'kysely:warning: outdated driver/plugin detected! QueryResult.numUpdatedOrDeletedRows is deprecated and will be removed in a future release.' + 'kysely:warning: outdated driver/plugin detected! QueryResult.numUpdatedOrDeletedRows is deprecated and will be removed in a future release.', ) } diff --git a/src/query-executor/query-executor.ts b/src/query-executor/query-executor.ts index 99bfc983b..d8e5fd05c 100644 --- a/src/query-executor/query-executor.ts +++ b/src/query-executor/query-executor.ts @@ -37,7 +37,7 @@ export interface QueryExecutor extends ConnectionProvider { */ compileQuery( node: RootOperationNode, - queryId: QueryId + queryId: QueryId, ): CompiledQuery /** @@ -46,7 +46,7 @@ export interface QueryExecutor extends ConnectionProvider { */ executeQuery( compiledQuery: CompiledQuery, - queryId: QueryId + queryId: QueryId, ): Promise> /** @@ -61,7 +61,7 @@ export interface QueryExecutor extends ConnectionProvider { * only by the postgres driver. */ chunkSize: number, - queryId: QueryId + queryId: QueryId, ): AsyncIterableIterator> /** diff --git a/src/raw-builder/raw-builder.ts b/src/raw-builder/raw-builder.ts index 102fc7957..aeb73467d 100644 --- a/src/raw-builder/raw-builder.ts +++ b/src/raw-builder/raw-builder.ts @@ -4,13 +4,17 @@ import { RawNode } from '../operation-node/raw-node.js' import { CompiledQuery } from '../query-compiler/compiled-query.js' import { preventAwait } from '../util/prevent-await.js' import { QueryExecutor } from '../query-executor/query-executor.js' -import { freeze, isFunction, isObject } from '../util/object-utils.js' +import { freeze } from '../util/object-utils.js' import { KyselyPlugin } from '../plugin/kysely-plugin.js' import { NOOP_QUERY_EXECUTOR } from '../query-executor/noop-query-executor.js' import { QueryExecutorProvider } from '../query-executor/query-executor-provider.js' import { QueryId } from '../util/query-id.js' import { IdentifierNode } from '../operation-node/identifier-node.js' -import { AliasedExpression, Expression } from '../expression/expression.js' +import { + AliasableExpression, + AliasedExpression, + Expression, +} from '../expression/expression.js' import { isOperationNodeSource } from '../operation-node/operation-node-source.js' /** @@ -19,17 +23,8 @@ import { isOperationNodeSource } from '../operation-node/operation-node-source.j * You shouldn't need to create `RawBuilder` instances directly. Instead you should * use the {@link sql} template tag. */ -export class RawBuilder implements Expression { - readonly #props: RawBuilderProps - - constructor(props: RawBuilderProps) { - this.#props = freeze(props) - } - - /** @private */ - get expressionType(): O | undefined { - return undefined - } +export interface RawBuilder extends AliasableExpression { + get isRawBuilder(): true /** * Returns an aliased version of the SQL expression. @@ -86,9 +81,6 @@ export class RawBuilder implements Expression { */ as(alias: A): AliasedRawBuilder as(alias: Expression): AliasedRawBuilder - as(alias: string | Expression): AliasedRawBuilder { - return new AliasedRawBuilder(this, alias) - } /** * Change the output type of the raw expression. @@ -96,22 +88,79 @@ export class RawBuilder implements Expression { * This method call doesn't change the SQL in any way. This methods simply * returns a copy of this `RawBuilder` with a new output type. */ - $castTo(): RawBuilder { - return new RawBuilder({ ...this.#props }) - } + $castTo(): RawBuilder /** - * @deprecated Use `$castTo` instead. + * 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. */ - castTo(): RawBuilder { - return this.$castTo() - } + $notNull(): RawBuilder> /** * Adds a plugin for this SQL snippet. */ + withPlugin(plugin: KyselyPlugin): RawBuilder + + /** + * Compiles the builder to a `CompiledQuery`. + * + * ### Examples + * + * ```ts + * const { sql } = sql`select * from ${sql.table('person')}`.compile(db) + * console.log(sql) + * ``` + */ + compile(executorProvider: QueryExecutorProvider): CompiledQuery + + /** + * Executes the raw query. + * + * ### Examples + * + * ```ts + * const result = await sql`select * from ${sql.table('person')}`.execute(db) + * ``` + */ + execute(executorProvider: QueryExecutorProvider): Promise> + + toOperationNode(): RawNode +} + +class RawBuilderImpl implements RawBuilder { + readonly #props: RawBuilderProps + + constructor(props: RawBuilderProps) { + this.#props = freeze(props) + } + + get expressionType(): O | undefined { + return undefined + } + + get isRawBuilder(): true { + return true + } + + as(alias: string | Expression): AliasedRawBuilder { + return new AliasedRawBuilderImpl(this, alias) + } + + $castTo(): RawBuilder { + return new RawBuilderImpl({ ...this.#props }) + } + + $notNull(): RawBuilder> { + return new RawBuilderImpl(this.#props) + } + withPlugin(plugin: KyselyPlugin): RawBuilder { - return new RawBuilder({ + return new RawBuilderImpl({ ...this.#props, plugins: this.#props.plugins !== undefined @@ -129,13 +178,13 @@ export class RawBuilder implements Expression { } async execute( - executorProvider: QueryExecutorProvider + executorProvider: QueryExecutorProvider, ): Promise> { const executor = this.#getExecutor(executorProvider) return executor.executeQuery( this.#compile(executor), - this.#props.queryId + this.#props.queryId, ) } @@ -157,32 +206,36 @@ export class RawBuilder implements Expression { #compile(executor: QueryExecutor): CompiledQuery { return executor.compileQuery( this.#toOperationNode(executor), - this.#props.queryId + this.#props.queryId, ) } } -export function isRawBuilder(obj: unknown): obj is RawBuilder { - return ( - isObject(obj) && - isFunction(obj.as) && - isFunction(obj.$castTo) && - isFunction(obj.withPlugin) && - isFunction(obj.toOperationNode) && - isFunction(obj.execute) - ) +export interface RawBuilderProps { + readonly queryId: QueryId + readonly rawNode: RawNode + readonly plugins?: ReadonlyArray +} + +export function createRawBuilder(props: RawBuilderProps): RawBuilder { + return new RawBuilderImpl(props) } preventAwait( - RawBuilder, - "don't await RawBuilder instances directly. To execute the query you need to call `execute`" + RawBuilderImpl, + "don't await RawBuilder instances directly. To execute the query you need to call `execute`", ) /** * {@link RawBuilder} with an alias. The result of calling {@link RawBuilder.as}. */ -export class AliasedRawBuilder - implements AliasedExpression +export interface AliasedRawBuilder + extends AliasedExpression { + get rawBuilder(): RawBuilder +} + +class AliasedRawBuilderImpl + implements AliasedRawBuilder { readonly #rawBuilder: RawBuilder readonly #alias: A | Expression @@ -192,28 +245,29 @@ export class AliasedRawBuilder this.#alias = alias } - /** @private */ get expression(): Expression { return this.#rawBuilder } - /** @private */ get alias(): A | Expression { return this.#alias } + get rawBuilder(): RawBuilder { + return this.#rawBuilder + } + toOperationNode(): AliasNode { return AliasNode.create( this.#rawBuilder.toOperationNode(), isOperationNodeSource(this.#alias) ? this.#alias.toOperationNode() - : IdentifierNode.create(this.#alias) + : IdentifierNode.create(this.#alias), ) } } -export interface RawBuilderProps { - readonly queryId: QueryId - readonly rawNode: RawNode - readonly plugins?: ReadonlyArray -} +preventAwait( + AliasedRawBuilderImpl, + "don't await AliasedRawBuilder instances directly. AliasedRawBuilder should never be executed directly since it's always a part of another query.", +) diff --git a/src/raw-builder/sql.ts b/src/raw-builder/sql.ts index fd9c731e7..5ed887fd5 100644 --- a/src/raw-builder/sql.ts +++ b/src/raw-builder/sql.ts @@ -1,4 +1,5 @@ import { IdentifierNode } from '../operation-node/identifier-node.js' +import { isOperationNodeSource } from '../operation-node/operation-node-source.js' import { OperationNode } from '../operation-node/operation-node.js' import { RawNode } from '../operation-node/raw-node.js' import { ValueNode } from '../operation-node/value-node.js' @@ -6,7 +7,7 @@ import { parseStringReference } from '../parser/reference-parser.js' import { parseTable } from '../parser/table-parser.js' import { parseValueExpression } from '../parser/value-parser.js' import { createQueryId } from '../util/query-id.js' -import { RawBuilder } from './raw-builder.js' +import { RawBuilder, createRawBuilder } from './raw-builder.js' export interface Sql { /** @@ -42,12 +43,12 @@ export interface Sql { * // method to give it an alias. * sql`concat(first_name, ' ', last_name)`.as('full_name') * ) - * .where(sql`birthdate between ${date1} and ${date2}`) + * .where(sql`birthdate between ${date1} and ${date2}`) * // Here we assume we have list of nicknames for the person * // (a list of strings) and we use the PostgreSQL `@>` operator * // to test if all of them are valid nicknames for the user. - * .where('nicknames', '@>', sql`ARRAY[${sql.join(nicknames)}]`) - * .orderBy(sql`concat(first_name, ' ', last_name)`) + * .where('nicknames', '@>', sql`ARRAY[${sql.join(nicknames)}]`) + * .orderBy(sql`concat(first_name, ' ', last_name)`) * .execute() * ``` * @@ -72,7 +73,7 @@ export interface Sql { * * ```ts * const petName = db.selectFrom('pet').select('name').limit(1) - * const fullName = sql`concat(first_name, ' ', last_name)` + * const fullName = sql`concat(first_name, ' ', last_name)` * * sql` * select ${fullName} as full_name, ${petName} as pet_name @@ -322,7 +323,7 @@ export interface Sql { * return db * .selectFrom('person') * .selectAll() - * .where('nicknames', '@>', sql`ARRAY[${sql.join(nicknames)}]`) + * .where('nicknames', '@>', sql`ARRAY[${sql.join(nicknames)}]`) * .execute() * } * ``` @@ -365,7 +366,7 @@ export interface Sql { */ join( array: readonly unknown[], - separator?: RawBuilder + separator?: RawBuilder, ): RawBuilder } @@ -374,24 +375,24 @@ export const sql: Sql = Object.assign( sqlFragments: TemplateStringsArray, ...parameters: unknown[] ): RawBuilder => { - return new RawBuilder({ + return createRawBuilder({ queryId: createQueryId(), rawNode: RawNode.create( sqlFragments, - parameters?.map(parseValueExpression) ?? [] + parameters?.map(parseParameter) ?? [], ), }) }, { ref(columnReference: string): RawBuilder { - return new RawBuilder({ + return createRawBuilder({ queryId: createQueryId(), rawNode: RawNode.createWithChild(parseStringReference(columnReference)), }) }, val(value: V): RawBuilder { - return new RawBuilder({ + return createRawBuilder({ queryId: createQueryId(), rawNode: RawNode.createWithChild(parseValueExpression(value)), }) @@ -402,7 +403,7 @@ export const sql: Sql = Object.assign( }, table(tableReference: string): RawBuilder { - return new RawBuilder({ + return createRawBuilder({ queryId: createQueryId(), rawNode: RawNode.createWithChild(parseTable(tableReference)), }) @@ -414,14 +415,14 @@ export const sql: Sql = Object.assign( fragments[0] = '' fragments[fragments.length - 1] = '' - return new RawBuilder({ + return createRawBuilder({ queryId: createQueryId(), rawNode: RawNode.create(fragments, ids.map(IdentifierNode.create)), }) }, lit(value: V): RawBuilder { - return new RawBuilder({ + return createRawBuilder({ queryId: createQueryId(), rawNode: RawNode.createWithChild(ValueNode.createImmediate(value)), }) @@ -432,7 +433,7 @@ export const sql: Sql = Object.assign( }, raw(sql: string): RawBuilder { - return new RawBuilder({ + return createRawBuilder({ queryId: createQueryId(), rawNode: RawNode.createWithSql(sql), }) @@ -440,23 +441,31 @@ export const sql: Sql = Object.assign( join( array: readonly unknown[], - separator: RawBuilder = sql`, ` + separator: RawBuilder = sql`, `, ): RawBuilder { const nodes = new Array(2 * array.length - 1) const sep = separator.toOperationNode() for (let i = 0; i < array.length; ++i) { - nodes[2 * i] = parseValueExpression(array[i]) + nodes[2 * i] = parseParameter(array[i]) if (i !== array.length - 1) { nodes[2 * i + 1] = sep } } - return new RawBuilder({ + return createRawBuilder({ queryId: createQueryId(), rawNode: RawNode.createWithChildren(nodes), }) }, - } + }, ) + +function parseParameter(param: unknown): OperationNode { + if (isOperationNodeSource(param)) { + return param.toOperationNode() + } + + return parseValueExpression(param) +} diff --git a/src/schema/alter-column-builder.ts b/src/schema/alter-column-builder.ts index 70b8ed0d6..caa41b04d 100644 --- a/src/schema/alter-column-builder.ts +++ b/src/schema/alter-column-builder.ts @@ -18,31 +18,39 @@ export class AlterColumnBuilder { setDataType(dataType: DataTypeExpression): AlteredColumnBuilder { return new AlteredColumnBuilder( - AlterColumnNode.create(this.#column, 'dataType', parseDataTypeExpression(dataType)) + AlterColumnNode.create( + this.#column, + 'dataType', + parseDataTypeExpression(dataType), + ), ) } setDefault(value: DefaultValueExpression): AlteredColumnBuilder { return new AlteredColumnBuilder( - AlterColumnNode.create(this.#column, 'setDefault', parseDefaultValueExpression(value)) + AlterColumnNode.create( + this.#column, + 'setDefault', + parseDefaultValueExpression(value), + ), ) } dropDefault(): AlteredColumnBuilder { return new AlteredColumnBuilder( - AlterColumnNode.create(this.#column, 'dropDefault', true) + AlterColumnNode.create(this.#column, 'dropDefault', true), ) } setNotNull(): AlteredColumnBuilder { return new AlteredColumnBuilder( - AlterColumnNode.create(this.#column, 'setNotNull', true) + AlterColumnNode.create(this.#column, 'setNotNull', true), ) } dropNotNull(): AlteredColumnBuilder { return new AlteredColumnBuilder( - AlterColumnNode.create(this.#column, 'dropNotNull', true) + AlterColumnNode.create(this.#column, 'dropNotNull', true), ) } @@ -63,15 +71,14 @@ export class AlterColumnBuilder { * ```ts * db.schema.alterTable('person').alterColumn('age', (ac) => ac) * ``` - * + * * ```ts * db.schema.alterTable('person').alterColumn('age', (ac) => ac.dropNotNull().setNotNull()) * ``` * * Which would now throw a compilation error, instead of a runtime error. */ -export class AlteredColumnBuilder implements OperationNodeSource -{ +export class AlteredColumnBuilder implements OperationNodeSource { readonly #alterColumnNode: AlterColumnNode constructor(alterColumnNode: AlterColumnNode) { @@ -84,5 +91,5 @@ export class AlteredColumnBuilder implements OperationNodeSource } export type AlterColumnBuilderCallback = ( - builder: AlterColumnBuilder + builder: AlterColumnBuilder, ) => AlteredColumnBuilder diff --git a/src/schema/alter-table-add-foreign-key-constraint-builder.ts b/src/schema/alter-table-add-foreign-key-constraint-builder.ts index ae0b3166c..4bdc3165d 100644 --- a/src/schema/alter-table-add-foreign-key-constraint-builder.ts +++ b/src/schema/alter-table-add-foreign-key-constraint-builder.ts @@ -26,7 +26,7 @@ export class AlterTableAddForeignKeyConstraintBuilder } onDelete( - onDelete: OnModifyForeignAction + onDelete: OnModifyForeignAction, ): AlterTableAddForeignKeyConstraintBuilder { return new AlterTableAddForeignKeyConstraintBuilder({ ...this.#props, @@ -35,7 +35,7 @@ export class AlterTableAddForeignKeyConstraintBuilder } onUpdate( - onUpdate: OnModifyForeignAction + onUpdate: OnModifyForeignAction, ): AlterTableAddForeignKeyConstraintBuilder { return new AlterTableAddForeignKeyConstraintBuilder({ ...this.#props, @@ -55,17 +55,17 @@ export class AlterTableAddForeignKeyConstraintBuilder return this.#props.executor.transformQuery( AlterTableNode.cloneWithTableProps(this.#props.node, { addConstraint: AddConstraintNode.create( - this.#props.constraintBuilder.toOperationNode() + this.#props.constraintBuilder.toOperationNode(), ), }), - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -83,5 +83,5 @@ export interface AlterTableAddForeignKeyConstraintBuilderProps { preventAwait( AlterTableAddForeignKeyConstraintBuilder, - "don't await AlterTableAddForeignKeyConstraintBuilder instances directly. To execute the query you need to call `execute`" + "don't await AlterTableAddForeignKeyConstraintBuilder instances directly. To execute the query you need to call `execute`", ) diff --git a/src/schema/alter-table-add-index-builder.ts b/src/schema/alter-table-add-index-builder.ts new file mode 100644 index 000000000..6110883a0 --- /dev/null +++ b/src/schema/alter-table-add-index-builder.ts @@ -0,0 +1,197 @@ +import { Expression } from '../expression/expression.js' +import { AddIndexNode } from '../operation-node/add-index-node.js' +import { AlterTableNode } from '../operation-node/alter-table-node.js' +import { IndexType } from '../operation-node/create-index-node.js' +import { OperationNodeSource } from '../operation-node/operation-node-source.js' +import { RawNode } from '../operation-node/raw-node.js' +import { + OrderedColumnName, + parseOrderedColumnName, +} from '../parser/reference-parser.js' +import { CompiledQuery } from '../query-compiler/compiled-query.js' +import { QueryExecutor } from '../query-executor/query-executor.js' +import { Compilable } from '../util/compilable.js' +import { freeze } from '../util/object-utils.js' +import { preventAwait } from '../util/prevent-await.js' +import { QueryId } from '../util/query-id.js' + +export class AlterTableAddIndexBuilder + implements OperationNodeSource, Compilable +{ + readonly #props: AlterTableAddIndexBuilderProps + + constructor(props: AlterTableAddIndexBuilderProps) { + this.#props = freeze(props) + } + + /** + * Makes the index unique. + */ + unique(): AlterTableAddIndexBuilder { + return new AlterTableAddIndexBuilder({ + ...this.#props, + node: AlterTableNode.cloneWithTableProps(this.#props.node, { + addIndex: AddIndexNode.cloneWith(this.#props.node.addIndex!, { + unique: true, + }), + }), + }) + } + + /** + * Adds a column to the index. + * + * Also see {@link columns} for adding multiple columns at once or {@link expression} + * for specifying an arbitrary expression. + * + * ### Examples + * + * ```ts + * await db.schema + * .alterTable('person') + * .createIndex('person_first_name_and_age_index') + * .column('first_name') + * .column('age desc') + * .execute() + * ``` + * + * The generated SQL (MySQL): + * + * ```sql + * alter table `person` add index `person_first_name_and_age_index` (`first_name`, `age` desc) + * ``` + */ + column( + column: OrderedColumnName, + ): AlterTableAddIndexBuilder { + return new AlterTableAddIndexBuilder({ + ...this.#props, + node: AlterTableNode.cloneWithTableProps(this.#props.node, { + addIndex: AddIndexNode.cloneWithColumns(this.#props.node.addIndex!, [ + parseOrderedColumnName(column), + ]), + }), + }) + } + + /** + * Specifies a list of columns for the index. + * + * Also see {@link column} for adding a single column or {@link expression} for + * specifying an arbitrary expression. + * + * ### Examples + * + * ```ts + * await db.schema + * .alterTable('person') + * .addIndex('person_first_name_and_age_index') + * .columns(['first_name', 'age desc']) + * .execute() + * ``` + * + * The generated SQL (MySQL): + * + * ```sql + * alter table `person` add index `person_first_name_and_age_index` (`first_name`, `age` desc) + * ``` + */ + columns( + columns: OrderedColumnName[], + ): AlterTableAddIndexBuilder { + return new AlterTableAddIndexBuilder({ + ...this.#props, + node: AlterTableNode.cloneWithTableProps(this.#props.node, { + addIndex: AddIndexNode.cloneWithColumns( + this.#props.node.addIndex!, + columns.map(parseOrderedColumnName), + ), + }), + }) + } + + /** + * Specifies an arbitrary expression for the index. + * + * ### Examples + * + * ```ts + * import { sql } from 'kysely' + * + * await db.schema + * .alterTable('person') + * .addIndex('person_first_name_index') + * .expression(sql`(first_name < 'Sami')`) + * .execute() + * ``` + * + * The generated SQL (MySQL): + * + * ```sql + * alter table `person` add index `person_first_name_index` ((first_name < 'Sami')) + * ``` + */ + expression(expression: Expression): AlterTableAddIndexBuilder { + return new AlterTableAddIndexBuilder({ + ...this.#props, + node: AlterTableNode.cloneWithTableProps(this.#props.node, { + addIndex: AddIndexNode.cloneWithColumns(this.#props.node.addIndex!, [ + expression.toOperationNode(), + ]), + }), + }) + } + + /** + * Specifies the index type. + */ + using(indexType: IndexType): AlterTableAddIndexBuilder + using(indexType: string): AlterTableAddIndexBuilder + using(indexType: string): AlterTableAddIndexBuilder { + return new AlterTableAddIndexBuilder({ + ...this.#props, + node: AlterTableNode.cloneWithTableProps(this.#props.node, { + addIndex: AddIndexNode.cloneWith(this.#props.node.addIndex!, { + using: RawNode.createWithSql(indexType), + }), + }), + }) + } + + /** + * Simply calls the provided function passing `this` as the only argument. `$call` returns + * what the provided function returns. + */ + $call(func: (qb: this) => T): T { + return func(this) + } + + toOperationNode(): AlterTableNode { + return this.#props.executor.transformQuery( + this.#props.node, + this.#props.queryId, + ) + } + + compile(): CompiledQuery { + return this.#props.executor.compileQuery( + this.toOperationNode(), + this.#props.queryId, + ) + } + + async execute(): Promise { + await this.#props.executor.executeQuery(this.compile(), this.#props.queryId) + } +} + +export interface AlterTableAddIndexBuilderProps { + readonly queryId: QueryId + readonly executor: QueryExecutor + readonly node: AlterTableNode +} + +preventAwait( + AlterTableAddIndexBuilder, + "don't await AlterTableAddIndexBuilder instances directly. To execute the query you need to call `execute`", +) diff --git a/src/schema/alter-table-builder.ts b/src/schema/alter-table-builder.ts index 1f22a2d97..c55901b8d 100644 --- a/src/schema/alter-table-builder.ts +++ b/src/schema/alter-table-builder.ts @@ -1,5 +1,4 @@ import { AddColumnNode } from '../operation-node/add-column-node.js' -import { AlterColumnNode } from '../operation-node/alter-column-node.js' import { AlterTableNode } from '../operation-node/alter-table-node.js' import { ColumnDefinitionNode } from '../operation-node/column-definition-node.js' import { DropColumnNode } from '../operation-node/drop-column-node.js' @@ -37,6 +36,14 @@ import { import { AlterTableExecutor } from './alter-table-executor.js' import { AlterTableAddForeignKeyConstraintBuilder } from './alter-table-add-foreign-key-constraint-builder.js' import { AlterTableDropConstraintBuilder } from './alter-table-drop-constraint-builder.js' +import { PrimaryConstraintNode } from '../operation-node/primary-constraint-node.js' +import { DropIndexNode } from '../operation-node/drop-index-node.js' +import { AddIndexNode } from '../operation-node/add-index-node.js' +import { AlterTableAddIndexBuilder } from './alter-table-add-index-builder.js' +import { + UniqueConstraintNodeBuilder, + UniqueConstraintNodeBuilderCallback, +} from './unique-constraint-builder.js' /** * This builder can be used to create a `alter table` query. @@ -68,17 +75,15 @@ export class AlterTableBuilder implements ColumnAlteringInterface { alterColumn( column: string, - alteration: AlterColumnBuilderCallback + alteration: AlterColumnBuilderCallback, ): AlterTableColumnAlteringBuilder { - const builder = alteration( - new AlterColumnBuilder(column) - ) + const builder = alteration(new AlterColumnBuilder(column)) return new AlterTableColumnAlteringBuilder({ ...this.#props, node: AlterTableNode.cloneWithColumnAlteration( this.#props.node, - builder.toOperationNode() + builder.toOperationNode(), ), }) } @@ -88,20 +93,20 @@ export class AlterTableBuilder implements ColumnAlteringInterface { ...this.#props, node: AlterTableNode.cloneWithColumnAlteration( this.#props.node, - DropColumnNode.create(column) + DropColumnNode.create(column), ), }) } renameColumn( column: string, - newColumn: string + newColumn: string, ): AlterTableColumnAlteringBuilder { return new AlterTableColumnAlteringBuilder({ ...this.#props, node: AlterTableNode.cloneWithColumnAlteration( this.#props.node, - RenameColumnNode.create(column, newColumn) + RenameColumnNode.create(column, newColumn), ), }) } @@ -109,22 +114,22 @@ export class AlterTableBuilder implements ColumnAlteringInterface { addColumn( columnName: string, dataType: DataTypeExpression, - build: ColumnDefinitionBuilderCallback = noop + build: ColumnDefinitionBuilderCallback = noop, ): AlterTableColumnAlteringBuilder { const builder = build( new ColumnDefinitionBuilder( ColumnDefinitionNode.create( columnName, - parseDataTypeExpression(dataType) - ) - ) + parseDataTypeExpression(dataType), + ), + ), ) return new AlterTableColumnAlteringBuilder({ ...this.#props, node: AlterTableNode.cloneWithColumnAlteration( this.#props.node, - AddColumnNode.create(builder.toOperationNode()) + AddColumnNode.create(builder.toOperationNode()), ), }) } @@ -132,22 +137,22 @@ export class AlterTableBuilder implements ColumnAlteringInterface { modifyColumn( columnName: string, dataType: DataTypeExpression, - build: ColumnDefinitionBuilderCallback = noop + build: ColumnDefinitionBuilderCallback = noop, ): AlterTableColumnAlteringBuilder { const builder = build( new ColumnDefinitionBuilder( ColumnDefinitionNode.create( columnName, - parseDataTypeExpression(dataType) - ) - ) + parseDataTypeExpression(dataType), + ), + ), ) return new AlterTableColumnAlteringBuilder({ ...this.#props, node: AlterTableNode.cloneWithColumnAlteration( this.#props.node, - ModifyColumnNode.create(builder.toOperationNode()) + ModifyColumnNode.create(builder.toOperationNode()), ), }) } @@ -157,13 +162,20 @@ export class AlterTableBuilder implements ColumnAlteringInterface { */ addUniqueConstraint( constraintName: string, - columns: string[] + columns: string[], + build: UniqueConstraintNodeBuilderCallback = noop, ): AlterTableExecutor { + const uniqueConstraintBuilder = build( + new UniqueConstraintNodeBuilder( + UniqueConstraintNode.create(columns, constraintName), + ), + ) + return new AlterTableExecutor({ ...this.#props, node: AlterTableNode.cloneWithTableProps(this.#props.node, { addConstraint: AddConstraintNode.create( - UniqueConstraintNode.create(columns, constraintName) + uniqueConstraintBuilder.toOperationNode(), ), }), }) @@ -174,7 +186,7 @@ export class AlterTableBuilder implements ColumnAlteringInterface { */ addCheckConstraint( constraintName: string, - checkExpression: Expression + checkExpression: Expression, ): AlterTableExecutor { return new AlterTableExecutor({ ...this.#props, @@ -182,8 +194,8 @@ export class AlterTableBuilder implements ColumnAlteringInterface { addConstraint: AddConstraintNode.create( CheckConstraintNode.create( checkExpression.toOperationNode(), - constraintName - ) + constraintName, + ), ), }), }) @@ -200,7 +212,7 @@ export class AlterTableBuilder implements ColumnAlteringInterface { constraintName: string, columns: string[], targetTable: string, - targetColumns: string[] + targetColumns: string[], ): AlterTableAddForeignKeyConstraintBuilder { return new AlterTableAddForeignKeyConstraintBuilder({ ...this.#props, @@ -209,12 +221,29 @@ export class AlterTableBuilder implements ColumnAlteringInterface { columns.map(ColumnNode.create), parseTable(targetTable), targetColumns.map(ColumnNode.create), - constraintName - ) + constraintName, + ), ), }) } + /** + * See {@link CreateTableBuilder.addPrimaryKeyConstraint} + */ + addPrimaryKeyConstraint( + constraintName: string, + columns: string[], + ): AlterTableExecutor { + return new AlterTableExecutor({ + ...this.#props, + node: AlterTableNode.cloneWithTableProps(this.#props.node, { + addConstraint: AddConstraintNode.create( + PrimaryConstraintNode.create(columns, constraintName), + ), + }), + }) + } + dropConstraint(constraintName: string): AlterTableDropConstraintBuilder { return new AlterTableDropConstraintBuilder({ ...this.#props, @@ -225,19 +254,66 @@ export class AlterTableBuilder implements ColumnAlteringInterface { } /** - * Calls the given function passing `this` as the only argument. + * This can be used to add index to table. * - * See {@link CreateTableBuilder.$call} + * ### Examples + * + * ```ts + * db.schema.alterTable('person') + * .addIndex('person_email_index') + * .column('email') + * .unique() + * .execute() + * ``` + * + * The generated SQL (MySQL): + * + * ```sql + * alter table `person` add unique index `person_email_index` (`email`) + * ``` */ - $call(func: (qb: this) => T): T { - return func(this) + addIndex(indexName: string): AlterTableAddIndexBuilder { + return new AlterTableAddIndexBuilder({ + ...this.#props, + node: AlterTableNode.cloneWithTableProps(this.#props.node, { + addIndex: AddIndexNode.create(indexName), + }), + }) } /** - * @deprecated Use `$call` instead + * This can be used to drop index from table. + * + * ### Examples + * + * ```ts + * db.schema.alterTable('person') + * .dropIndex('person_email_index') + * .execute() + * ``` + * + * The generated SQL (MySQL): + * + * ```sql + * alter table `person` drop index `test_first_name_index` + * ``` */ - call(func: (qb: this) => T): T { - return this.$call(func) + dropIndex(indexName: string): AlterTableExecutor { + return new AlterTableExecutor({ + ...this.#props, + node: AlterTableNode.cloneWithTableProps(this.#props.node, { + dropIndex: DropIndexNode.create(indexName), + }), + }) + } + + /** + * Calls the given function passing `this` as the only argument. + * + * See {@link CreateTableBuilder.$call} + */ + $call(func: (qb: this) => T): T { + return func(this) } } @@ -250,7 +326,7 @@ export interface AlterTableBuilderProps { export interface ColumnAlteringInterface { alterColumn( column: string, - alteration: AlterColumnBuilderCallback + alteration: AlterColumnBuilderCallback, ): ColumnAlteringInterface dropColumn(column: string): ColumnAlteringInterface @@ -263,7 +339,7 @@ export interface ColumnAlteringInterface { addColumn( columnName: string, dataType: DataTypeExpression, - build?: ColumnDefinitionBuilderCallback + build?: ColumnDefinitionBuilderCallback, ): ColumnAlteringInterface /** @@ -274,7 +350,7 @@ export interface ColumnAlteringInterface { modifyColumn( columnName: string, dataType: DataTypeExpression, - build: ColumnDefinitionBuilderCallback + build: ColumnDefinitionBuilderCallback, ): ColumnAlteringInterface } @@ -289,17 +365,15 @@ export class AlterTableColumnAlteringBuilder alterColumn( column: string, - alteration: AlterColumnBuilderCallback + alteration: AlterColumnBuilderCallback, ): AlterTableColumnAlteringBuilder { - const builder = alteration( - new AlterColumnBuilder(column) - ) + const builder = alteration(new AlterColumnBuilder(column)) return new AlterTableColumnAlteringBuilder({ ...this.#props, node: AlterTableNode.cloneWithColumnAlteration( this.#props.node, - builder.toOperationNode() + builder.toOperationNode(), ), }) } @@ -309,20 +383,20 @@ export class AlterTableColumnAlteringBuilder ...this.#props, node: AlterTableNode.cloneWithColumnAlteration( this.#props.node, - DropColumnNode.create(column) + DropColumnNode.create(column), ), }) } renameColumn( column: string, - newColumn: string + newColumn: string, ): AlterTableColumnAlteringBuilder { return new AlterTableColumnAlteringBuilder({ ...this.#props, node: AlterTableNode.cloneWithColumnAlteration( this.#props.node, - RenameColumnNode.create(column, newColumn) + RenameColumnNode.create(column, newColumn), ), }) } @@ -330,22 +404,22 @@ export class AlterTableColumnAlteringBuilder addColumn( columnName: string, dataType: DataTypeExpression, - build: ColumnDefinitionBuilderCallback = noop + build: ColumnDefinitionBuilderCallback = noop, ): AlterTableColumnAlteringBuilder { const builder = build( new ColumnDefinitionBuilder( ColumnDefinitionNode.create( columnName, - parseDataTypeExpression(dataType) - ) - ) + parseDataTypeExpression(dataType), + ), + ), ) return new AlterTableColumnAlteringBuilder({ ...this.#props, node: AlterTableNode.cloneWithColumnAlteration( this.#props.node, - AddColumnNode.create(builder.toOperationNode()) + AddColumnNode.create(builder.toOperationNode()), ), }) } @@ -353,22 +427,22 @@ export class AlterTableColumnAlteringBuilder modifyColumn( columnName: string, dataType: DataTypeExpression, - build: ColumnDefinitionBuilderCallback = noop + build: ColumnDefinitionBuilderCallback = noop, ): AlterTableColumnAlteringBuilder { const builder = build( new ColumnDefinitionBuilder( ColumnDefinitionNode.create( columnName, - parseDataTypeExpression(dataType) - ) - ) + parseDataTypeExpression(dataType), + ), + ), ) return new AlterTableColumnAlteringBuilder({ ...this.#props, node: AlterTableNode.cloneWithColumnAlteration( this.#props.node, - ModifyColumnNode.create(builder.toOperationNode()) + ModifyColumnNode.create(builder.toOperationNode()), ), }) } @@ -376,14 +450,14 @@ export class AlterTableColumnAlteringBuilder toOperationNode(): AlterTableNode { return this.#props.executor.transformQuery( this.#props.node, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -400,5 +474,5 @@ preventAwait(AlterColumnBuilder, "don't await AlterColumnBuilder instances") preventAwait( AlterTableColumnAlteringBuilder, - "don't await AlterTableColumnAlteringBuilder instances directly. To execute the query you need to call `execute`" + "don't await AlterTableColumnAlteringBuilder instances directly. To execute the query you need to call `execute`", ) diff --git a/src/schema/alter-table-drop-constraint-builder.ts b/src/schema/alter-table-drop-constraint-builder.ts index abf17f4ea..e6b4199be 100644 --- a/src/schema/alter-table-drop-constraint-builder.ts +++ b/src/schema/alter-table-drop-constraint-builder.ts @@ -25,7 +25,7 @@ export class AlterTableDropConstraintBuilder this.#props.node.dropConstraint!, { ifExists: true, - } + }, ), }), }) @@ -39,7 +39,7 @@ export class AlterTableDropConstraintBuilder this.#props.node.dropConstraint!, { modifier: 'cascade', - } + }, ), }), }) @@ -53,7 +53,7 @@ export class AlterTableDropConstraintBuilder this.#props.node.dropConstraint!, { modifier: 'restrict', - } + }, ), }), }) @@ -70,14 +70,14 @@ export class AlterTableDropConstraintBuilder toOperationNode(): AlterTableNode { return this.#props.executor.transformQuery( this.#props.node, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -94,5 +94,5 @@ export interface AlterTableDropConstraintBuilderProps { preventAwait( AlterTableDropConstraintBuilder, - "don't await AlterTableDropConstraintBuilder instances directly. To execute the query you need to call `execute`" + "don't await AlterTableDropConstraintBuilder instances directly. To execute the query you need to call `execute`", ) diff --git a/src/schema/alter-table-executor.ts b/src/schema/alter-table-executor.ts index 062468ae7..08a172eb3 100644 --- a/src/schema/alter-table-executor.ts +++ b/src/schema/alter-table-executor.ts @@ -17,14 +17,14 @@ export class AlterTableExecutor implements OperationNodeSource, Compilable { toOperationNode(): AlterTableNode { return this.#props.executor.transformQuery( this.#props.node, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -41,5 +41,5 @@ export interface AlterTableExecutorProps { preventAwait( AlterTableExecutor, - "don't await AlterTableExecutor instances directly. To execute the query you need to call `execute`" + "don't await AlterTableExecutor instances directly. To execute the query you need to call `execute`", ) diff --git a/src/schema/column-definition-builder.ts b/src/schema/column-definition-builder.ts index 0a6edf5ef..3f638b765 100644 --- a/src/schema/column-definition-builder.ts +++ b/src/schema/column-definition-builder.ts @@ -1,6 +1,5 @@ import { CheckConstraintNode } from '../operation-node/check-constraint-node.js' import { OperationNodeSource } from '../operation-node/operation-node-source.js' -import { ReferenceNode } from '../operation-node/reference-node.js' import { OnModifyForeignAction, ReferencesNode, @@ -34,7 +33,20 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { */ autoIncrement(): ColumnDefinitionBuilder { return new ColumnDefinitionBuilder( - ColumnDefinitionNode.cloneWith(this.#node, { autoIncrement: true }) + ColumnDefinitionNode.cloneWith(this.#node, { autoIncrement: true }), + ) + } + + /** + * Makes the column an identity column. + * + * This only works on some dialects like MS SQL Server (MSSQL). + * + * For PostgreSQL's `generated always as identity` use {@link generatedAlwaysAsIdentity}. + */ + identity(): ColumnDefinitionBuilder { + return new ColumnDefinitionBuilder( + ColumnDefinitionNode.cloneWith(this.#node, { identity: true }) ) } @@ -46,7 +58,7 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { */ primaryKey(): ColumnDefinitionBuilder { return new ColumnDefinitionBuilder( - ColumnDefinitionNode.cloneWith(this.#node, { primaryKey: true }) + ColumnDefinitionNode.cloneWith(this.#node, { primaryKey: true }), ) } @@ -66,9 +78,9 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { references(ref: string): ColumnDefinitionBuilder { const references = parseStringReference(ref) - if (!ReferenceNode.is(references) || SelectAllNode.is(references.column)) { + if (!references.table || SelectAllNode.is(references.column)) { throw new Error( - `invalid call references('${ref}'). The reference must have format table.column or schema.table.column` + `invalid call references('${ref}'). The reference must have format table.column or schema.table.column`, ) } @@ -77,7 +89,7 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { references: ReferencesNode.create(references.table, [ references.column, ]), - }) + }), ) } @@ -103,9 +115,9 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { ColumnDefinitionNode.cloneWith(this.#node, { references: ReferencesNode.cloneWithOnDelete( this.#node.references, - parseOnModifyForeignAction(onDelete) + parseOnModifyForeignAction(onDelete), ), - }) + }), ) } @@ -127,9 +139,9 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { ColumnDefinitionNode.cloneWith(this.#node, { references: ReferencesNode.cloneWithOnUpdate( this.#node.references, - parseOnModifyForeignAction(onUpdate) + parseOnModifyForeignAction(onUpdate), ), - }) + }), ) } @@ -138,7 +150,7 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { */ unique(): ColumnDefinitionBuilder { return new ColumnDefinitionBuilder( - ColumnDefinitionNode.cloneWith(this.#node, { unique: true }) + ColumnDefinitionNode.cloneWith(this.#node, { unique: true }), ) } @@ -147,7 +159,7 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { */ notNull(): ColumnDefinitionBuilder { return new ColumnDefinitionBuilder( - ColumnDefinitionNode.cloneWith(this.#node, { notNull: true }) + ColumnDefinitionNode.cloneWith(this.#node, { notNull: true }), ) } @@ -158,7 +170,7 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { */ unsigned(): ColumnDefinitionBuilder { return new ColumnDefinitionBuilder( - ColumnDefinitionNode.cloneWith(this.#node, { unsigned: true }) + ColumnDefinitionNode.cloneWith(this.#node, { unsigned: true }), ) } @@ -194,7 +206,7 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { return new ColumnDefinitionBuilder( ColumnDefinitionNode.cloneWith(this.#node, { defaultTo: DefaultValueNode.create(parseDefaultValueExpression(value)), - }) + }), ) } @@ -218,7 +230,7 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { return new ColumnDefinitionBuilder( ColumnDefinitionNode.cloneWith(this.#node, { check: CheckConstraintNode.create(expression.toOperationNode()), - }) + }), ) } @@ -242,20 +254,24 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { return new ColumnDefinitionBuilder( ColumnDefinitionNode.cloneWith(this.#node, { generated: GeneratedNode.createWithExpression( - expression.toOperationNode() + expression.toOperationNode(), ), - }) + }), ) } /** - * Adds the `generated always as identity` specifier on supported dialects. + * Adds the `generated always as identity` specifier. + * + * This only works on some dialects like PostgreSQL. + * + * For MS SQL Server (MSSQL)'s identity column use {@link identity}. */ generatedAlwaysAsIdentity(): ColumnDefinitionBuilder { return new ColumnDefinitionBuilder( ColumnDefinitionNode.cloneWith(this.#node, { generated: GeneratedNode.create({ identity: true, always: true }), - }) + }), ) } @@ -266,7 +282,7 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { return new ColumnDefinitionBuilder( ColumnDefinitionNode.cloneWith(this.#node, { generated: GeneratedNode.create({ identity: true, byDefault: true }), - }) + }), ) } @@ -296,7 +312,7 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { generated: GeneratedNode.cloneWith(this.#node.generated, { stored: true, }), - }) + }), ) } @@ -325,8 +341,48 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { return new ColumnDefinitionBuilder( ColumnDefinitionNode.cloneWithFrontModifier( this.#node, - modifier.toOperationNode() - ) + modifier.toOperationNode(), + ), + ) + } + + /** + * Adds `nulls not distinct` specifier. + * Should be used with `unique` constraint. + * + * This only works on some dialects like PostgreSQL. + * + * ### Examples + * + * ```ts + * db.schema.createTable('person') + * .addColumn('id', 'integer', col => col.primaryKey()) + * .addColumn('first_name', 'varchar(30)', col => col.unique().nullsNotDistinct()) + * .execute() + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * create table "person" ( + * "id" integer primary key, + * "first_name" varchar(30) unique nulls not distinct + * ) + * ``` + */ + nullsNotDistinct(): ColumnDefinitionBuilder { + return new ColumnDefinitionBuilder( + ColumnDefinitionNode.cloneWith(this.#node, { nullsNotDistinct: true }), + ) + } + + /** + * Adds `if not exists` specifier. + * This only works for PostgreSQL. + */ + ifNotExists(): ColumnDefinitionBuilder { + return new ColumnDefinitionBuilder( + ColumnDefinitionNode.cloneWith(this.#node, { ifNotExists: true }), ) } @@ -355,8 +411,8 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { return new ColumnDefinitionBuilder( ColumnDefinitionNode.cloneWithEndModifier( this.#node, - modifier.toOperationNode() - ) + modifier.toOperationNode(), + ), ) } @@ -375,9 +431,9 @@ export class ColumnDefinitionBuilder implements OperationNodeSource { preventAwait( ColumnDefinitionBuilder, - "don't await ColumnDefinitionBuilder instances directly." + "don't await ColumnDefinitionBuilder instances directly.", ) export type ColumnDefinitionBuilderCallback = ( - builder: ColumnDefinitionBuilder + builder: ColumnDefinitionBuilder, ) => ColumnDefinitionBuilder diff --git a/src/schema/create-index-builder.ts b/src/schema/create-index-builder.ts index 21a27e014..c2f6eca30 100644 --- a/src/schema/create-index-builder.ts +++ b/src/schema/create-index-builder.ts @@ -19,7 +19,7 @@ import { freeze } from '../util/object-utils.js' import { Expression } from '../expression/expression.js' import { ComparisonOperatorExpression, - parseWhere, + parseValueBinaryOperationOrExpression, } from '../parser/binary-operation-parser.js' import { QueryNode } from '../operation-node/query-node.js' import { ExpressionBuilder } from '../expression/expression-builder.js' @@ -61,6 +61,37 @@ export class CreateIndexBuilder }) } + /** + * Adds `nulls not distinct` specifier to index. + * This only works on some dialects like PostgreSQL. + * + * ### Examples + * + * ```ts + * db.schema.createIndex('person_first_name_index') + * .on('person') + * .column('first_name') + * .nullsNotDistinct() + * .execute() + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * create index "person_first_name_index" + * on "test" ("first_name") + * nulls not distinct; + * ``` + */ + nullsNotDistinct(): CreateIndexBuilder { + return new CreateIndexBuilder({ + ...this.#props, + node: CreateIndexNode.cloneWith(this.#props.node, { + nullsNotDistinct: true, + }), + }) + } + /** * Specifies the table for the index. */ @@ -97,7 +128,7 @@ export class CreateIndexBuilder * ``` */ column( - column: OrderedColumnName + column: OrderedColumnName, ): CreateIndexBuilder> { return new CreateIndexBuilder({ ...this.#props, @@ -130,13 +161,13 @@ export class CreateIndexBuilder * ``` */ columns( - columns: OrderedColumnName[] + columns: OrderedColumnName[], ): CreateIndexBuilder> { return new CreateIndexBuilder({ ...this.#props, node: CreateIndexNode.cloneWithColumns( this.#props.node, - columns.map(parseOrderedColumnName) + columns.map(parseOrderedColumnName), ), }) } @@ -219,7 +250,7 @@ export class CreateIndexBuilder where( lhs: C | Expression, op: ComparisonOperatorExpression, - rhs: unknown + rhs: unknown, ): CreateIndexBuilder where( @@ -227,11 +258,11 @@ export class CreateIndexBuilder qb: ExpressionBuilder< ShallowRecord>, string - > - ) => Expression + >, + ) => Expression, ): CreateIndexBuilder - where(expression: Expression): CreateIndexBuilder + where(expression: Expression): CreateIndexBuilder where(...args: any[]): any { const transformer = new ImmediateValueTransformer() @@ -240,7 +271,7 @@ export class CreateIndexBuilder ...this.#props, node: QueryNode.cloneWithWhere( this.#props.node, - transformer.transformNode(parseWhere(args)) + transformer.transformNode(parseValueBinaryOperationOrExpression(args)), ), }) } @@ -256,14 +287,14 @@ export class CreateIndexBuilder toOperationNode(): CreateIndexNode { return this.#props.executor.transformQuery( this.#props.node, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -274,7 +305,7 @@ export class CreateIndexBuilder preventAwait( CreateIndexBuilder, - "don't await CreateIndexBuilder instances directly. To execute the query you need to call `execute`" + "don't await CreateIndexBuilder instances directly. To execute the query you need to call `execute`", ) export interface CreateIndexBuilderProps { diff --git a/src/schema/create-schema-builder.ts b/src/schema/create-schema-builder.ts index c831b5529..dd5d6998e 100644 --- a/src/schema/create-schema-builder.ts +++ b/src/schema/create-schema-builder.ts @@ -32,14 +32,14 @@ export class CreateSchemaBuilder implements OperationNodeSource, Compilable { toOperationNode(): CreateSchemaNode { return this.#props.executor.transformQuery( this.#props.node, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -50,7 +50,7 @@ export class CreateSchemaBuilder implements OperationNodeSource, Compilable { preventAwait( CreateSchemaBuilder, - "don't await CreateSchemaBuilder instances directly. To execute the query you need to call `execute`" + "don't await CreateSchemaBuilder instances directly. To execute the query you need to call `execute`", ) export interface CreateSchemaBuilderProps { diff --git a/src/schema/create-table-builder.ts b/src/schema/create-table-builder.ts index 0aecbf3ab..9aefddaa1 100644 --- a/src/schema/create-table-builder.ts +++ b/src/schema/create-table-builder.ts @@ -24,6 +24,11 @@ import { CheckConstraintNode } from '../operation-node/check-constraint-node.js' import { parseTable } from '../parser/table-parser.js' import { parseOnCommitAction } from '../parser/on-commit-action-parse.js' import { Expression } from '../expression/expression.js' +import { + UniqueConstraintNodeBuilder, + UniqueConstraintNodeBuilderCallback, +} from './unique-constraint-builder.js' +import { parseExpression } from '../parser/expression-parser.js' /** * This builder can be used to create a `create table` query. @@ -103,7 +108,7 @@ export class CreateTableBuilder * ``` * * With this method, it's once again good to remember that Kysely just builds the - * query and doesn't provide the same API for all databses. For example, some + * query and doesn't provide the same API for all databases. For example, some * databases like older MySQL don't support the `references` statement in the * column definition. Instead foreign key constraints need to be defined in the * `create table` query. See the next example: @@ -129,22 +134,22 @@ export class CreateTableBuilder addColumn( columnName: CN, dataType: DataTypeExpression, - build: ColumnBuilderCallback = noop + build: ColumnBuilderCallback = noop, ): CreateTableBuilder { const columnBuilder = build( new ColumnDefinitionBuilder( ColumnDefinitionNode.create( columnName, - parseDataTypeExpression(dataType) - ) - ) + parseDataTypeExpression(dataType), + ), + ), ) return new CreateTableBuilder({ ...this.#props, node: CreateTableNode.cloneWithColumn( this.#props.node, - columnBuilder.toOperationNode() + columnBuilder.toOperationNode(), ), }) } @@ -163,13 +168,13 @@ export class CreateTableBuilder */ addPrimaryKeyConstraint( constraintName: string, - columns: C[] + columns: C[], ): CreateTableBuilder { return new CreateTableBuilder({ ...this.#props, node: CreateTableNode.cloneWithConstraint( this.#props.node, - PrimaryConstraintNode.create(columns, constraintName) + PrimaryConstraintNode.create(columns, constraintName), ), }) } @@ -185,16 +190,28 @@ export class CreateTableBuilder * ```ts * addUniqueConstraint('first_name_last_name_unique', ['first_name', 'last_name']) * ``` + * + * In dialects such as PostgreSQL you can specify `nulls not distinct` as follows: + * ```ts + * addUniqueConstraint('first_name_last_name_unique', ['first_name', 'last_name'], (builder) => builder.nullsNotDistinct()) + * ``` */ addUniqueConstraint( constraintName: string, - columns: C[] + columns: C[], + build: UniqueConstraintNodeBuilderCallback = noop, ): CreateTableBuilder { + const uniqueConstraintBuilder = build( + new UniqueConstraintNodeBuilder( + UniqueConstraintNode.create(columns, constraintName), + ), + ) + return new CreateTableBuilder({ ...this.#props, node: CreateTableNode.cloneWithConstraint( this.#props.node, - UniqueConstraintNode.create(columns, constraintName) + uniqueConstraintBuilder.toOperationNode(), ), }) } @@ -215,7 +232,7 @@ export class CreateTableBuilder */ addCheckConstraint( constraintName: string, - checkExpression: Expression + checkExpression: Expression, ): CreateTableBuilder { return new CreateTableBuilder({ ...this.#props, @@ -223,8 +240,8 @@ export class CreateTableBuilder this.#props.node, CheckConstraintNode.create( checkExpression.toOperationNode(), - constraintName - ) + constraintName, + ), ), }) } @@ -263,7 +280,7 @@ export class CreateTableBuilder columns: C[], targetTable: string, targetColumns: string[], - build: ForeignKeyConstraintBuilderCallback = noop + build: ForeignKeyConstraintBuilderCallback = noop, ): CreateTableBuilder { const builder = build( new ForeignKeyConstraintBuilder( @@ -271,16 +288,16 @@ export class CreateTableBuilder columns.map(ColumnNode.create), parseTable(targetTable), targetColumns.map(ColumnNode.create), - constraintName - ) - ) + constraintName, + ), + ), ) return new CreateTableBuilder({ ...this.#props, node: CreateTableNode.cloneWithConstraint( this.#props.node, - builder.toOperationNode() + builder.toOperationNode(), ), }) } @@ -316,7 +333,7 @@ export class CreateTableBuilder ...this.#props, node: CreateTableNode.cloneWithFrontModifier( this.#props.node, - modifier.toOperationNode() + modifier.toOperationNode(), ), }) } @@ -352,11 +369,39 @@ export class CreateTableBuilder ...this.#props, node: CreateTableNode.cloneWithEndModifier( this.#props.node, - modifier.toOperationNode() + modifier.toOperationNode(), ), }) } + /** + * Allows to create table from `select` query. + * + * ### Examples + * + * ```ts + * db.schema.createTable('copy') + * .temporary() + * .as(db.selectFrom('person').select(['first_name', 'last_name'])) + * .execute() + * ``` + * + * The generated SQL (PostgreSQL): + * + * ```sql + * create temporary table "copy" as + * select "first_name", "last_name" from "person" + * ``` + */ + as(expression: Expression) { + return new CreateTableBuilder({ + ...this.#props, + node: CreateTableNode.cloneWith(this.#props.node, { + selectQuery: parseExpression(expression), + }), + }) + } + /** * Calls the given function passing `this` as the only argument. * @@ -393,24 +438,17 @@ export class CreateTableBuilder return func(this) } - /** - * @deprecated Use `$call` instead - */ - call(func: (qb: this) => T): T { - return this.$call(func) - } - toOperationNode(): CreateTableNode { return this.#props.executor.transformQuery( this.#props.node, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -421,7 +459,7 @@ export class CreateTableBuilder preventAwait( CreateTableBuilder, - "don't await CreateTableBuilder instances directly. To execute the query you need to call `execute`" + "don't await CreateTableBuilder instances directly. To execute the query you need to call `execute`", ) export interface CreateTableBuilderProps { @@ -431,9 +469,9 @@ export interface CreateTableBuilderProps { } export type ColumnBuilderCallback = ( - builder: ColumnDefinitionBuilder + builder: ColumnDefinitionBuilder, ) => ColumnDefinitionBuilder export type ForeignKeyConstraintBuilderCallback = ( - builder: ForeignKeyConstraintBuilder + builder: ForeignKeyConstraintBuilder, ) => ForeignKeyConstraintBuilder diff --git a/src/schema/create-type-builder.ts b/src/schema/create-type-builder.ts index 27cd4c0ce..78b9a3e6e 100644 --- a/src/schema/create-type-builder.ts +++ b/src/schema/create-type-builder.ts @@ -17,7 +17,7 @@ export class CreateTypeBuilder implements OperationNodeSource, Compilable { toOperationNode(): CreateTypeNode { return this.#props.executor.transformQuery( this.#props.node, - this.#props.queryId + this.#props.queryId, ) } @@ -48,7 +48,7 @@ export class CreateTypeBuilder implements OperationNodeSource, Compilable { compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -59,7 +59,7 @@ export class CreateTypeBuilder implements OperationNodeSource, Compilable { preventAwait( CreateTypeBuilder, - "don't await CreateTypeBuilder instances directly. To execute the query you need to call `execute`" + "don't await CreateTypeBuilder instances directly. To execute the query you need to call `execute`", ) export interface CreateTypeBuilderProps { diff --git a/src/schema/create-view-builder.ts b/src/schema/create-view-builder.ts index 8159fcd33..50ff2e428 100644 --- a/src/schema/create-view-builder.ts +++ b/src/schema/create-view-builder.ts @@ -7,9 +7,9 @@ import { QueryId } from '../util/query-id.js' import { freeze } from '../util/object-utils.js' import { CreateViewNode } from '../operation-node/create-view-node.js' import { parseColumnName } from '../parser/reference-parser.js' -import { AnySelectQueryBuilder } from '../util/type-utils.js' import { ImmediateValuePlugin } from '../plugin/immediate-value/immediate-value-plugin.js' import { RawBuilder } from '../raw-builder/raw-builder.js' +import { SelectQueryBuilder } from '../query-builder/select-query-builder.js' export class CreateViewBuilder implements OperationNodeSource, Compilable { readonly #props: CreateViewBuilderProps @@ -80,7 +80,9 @@ export class CreateViewBuilder implements OperationNodeSource, Compilable { * string opening an SQL injection vulnerability. DO NOT pass unchecked user input * into the query or raw expression passed to this method! */ - as(query: AnySelectQueryBuilder | RawBuilder): CreateViewBuilder { + as( + query: SelectQueryBuilder | RawBuilder, + ): CreateViewBuilder { const queryNode = query .withPlugin(new ImmediateValuePlugin()) .toOperationNode() @@ -104,14 +106,14 @@ export class CreateViewBuilder implements OperationNodeSource, Compilable { toOperationNode(): CreateViewNode { return this.#props.executor.transformQuery( this.#props.node, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -122,7 +124,7 @@ export class CreateViewBuilder implements OperationNodeSource, Compilable { preventAwait( CreateViewBuilder, - "don't await CreateViewBuilder instances directly. To execute the query you need to call `execute`" + "don't await CreateViewBuilder instances directly. To execute the query you need to call `execute`", ) export interface CreateViewBuilderProps { diff --git a/src/schema/drop-index-builder.ts b/src/schema/drop-index-builder.ts index 13ed6c190..396b09ec9 100644 --- a/src/schema/drop-index-builder.ts +++ b/src/schema/drop-index-builder.ts @@ -57,14 +57,14 @@ export class DropIndexBuilder implements OperationNodeSource, Compilable { toOperationNode(): DropIndexNode { return this.#props.executor.transformQuery( this.#props.node, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -75,7 +75,7 @@ export class DropIndexBuilder implements OperationNodeSource, Compilable { preventAwait( DropIndexBuilder, - "don't await DropIndexBuilder instances directly. To execute the query you need to call `execute`" + "don't await DropIndexBuilder instances directly. To execute the query you need to call `execute`", ) export interface DropIndexBuilderProps { diff --git a/src/schema/drop-schema-builder.ts b/src/schema/drop-schema-builder.ts index dc5a814cc..fc248e219 100644 --- a/src/schema/drop-schema-builder.ts +++ b/src/schema/drop-schema-builder.ts @@ -43,14 +43,14 @@ export class DropSchemaBuilder implements OperationNodeSource, Compilable { toOperationNode(): DropSchemaNode { return this.#props.executor.transformQuery( this.#props.node, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -61,7 +61,7 @@ export class DropSchemaBuilder implements OperationNodeSource, Compilable { preventAwait( DropSchemaBuilder, - "don't await DropSchemaBuilder instances directly. To execute the query you need to call `execute`" + "don't await DropSchemaBuilder instances directly. To execute the query you need to call `execute`", ) export interface DropSchemaBuilderProps { diff --git a/src/schema/drop-table-builder.ts b/src/schema/drop-table-builder.ts index a293c3d1a..120dece01 100644 --- a/src/schema/drop-table-builder.ts +++ b/src/schema/drop-table-builder.ts @@ -43,14 +43,14 @@ export class DropTableBuilder implements OperationNodeSource, Compilable { toOperationNode(): DropTableNode { return this.#props.executor.transformQuery( this.#props.node, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -61,7 +61,7 @@ export class DropTableBuilder implements OperationNodeSource, Compilable { preventAwait( DropTableBuilder, - "don't await DropTableBuilder instances directly. To execute the query you need to call `execute`" + "don't await DropTableBuilder instances directly. To execute the query you need to call `execute`", ) export interface DropTableBuilderProps { diff --git a/src/schema/drop-type-builder.ts b/src/schema/drop-type-builder.ts index 85bcd4700..e783c37f6 100644 --- a/src/schema/drop-type-builder.ts +++ b/src/schema/drop-type-builder.ts @@ -34,14 +34,14 @@ export class DropTypeBuilder implements OperationNodeSource, Compilable { toOperationNode(): DropTypeNode { return this.#props.executor.transformQuery( this.#props.node, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -52,7 +52,7 @@ export class DropTypeBuilder implements OperationNodeSource, Compilable { preventAwait( DropTypeBuilder, - "don't await DropTypeBuilder instances directly. To execute the query you need to call `execute`" + "don't await DropTypeBuilder instances directly. To execute the query you need to call `execute`", ) export interface DropTypeBuilderProps { diff --git a/src/schema/drop-view-builder.ts b/src/schema/drop-view-builder.ts index 95141c43c..33634cad9 100644 --- a/src/schema/drop-view-builder.ts +++ b/src/schema/drop-view-builder.ts @@ -52,14 +52,14 @@ export class DropViewBuilder implements OperationNodeSource, Compilable { toOperationNode(): DropViewNode { return this.#props.executor.transformQuery( this.#props.node, - this.#props.queryId + this.#props.queryId, ) } compile(): CompiledQuery { return this.#props.executor.compileQuery( this.toOperationNode(), - this.#props.queryId + this.#props.queryId, ) } @@ -70,7 +70,7 @@ export class DropViewBuilder implements OperationNodeSource, Compilable { preventAwait( DropViewBuilder, - "don't await DropViewBuilder instances directly. To execute the query you need to call `execute`" + "don't await DropViewBuilder instances directly. To execute the query you need to call `execute`", ) export interface DropViewBuilderProps { diff --git a/src/schema/foreign-key-constraint-builder.ts b/src/schema/foreign-key-constraint-builder.ts index eb94c8a49..5a7e45fa5 100644 --- a/src/schema/foreign-key-constraint-builder.ts +++ b/src/schema/foreign-key-constraint-builder.ts @@ -24,7 +24,7 @@ export class ForeignKeyConstraintBuilder return new ForeignKeyConstraintBuilder( ForeignKeyConstraintNode.cloneWith(this.#node, { onDelete: parseOnModifyForeignAction(onDelete), - }) + }), ) } @@ -32,7 +32,7 @@ export class ForeignKeyConstraintBuilder return new ForeignKeyConstraintBuilder( ForeignKeyConstraintNode.cloneWith(this.#node, { onUpdate: parseOnModifyForeignAction(onUpdate), - }) + }), ) } @@ -51,5 +51,5 @@ export class ForeignKeyConstraintBuilder preventAwait( ForeignKeyConstraintBuilder, - "don't await ForeignKeyConstraintBuilder instances directly." + "don't await ForeignKeyConstraintBuilder instances directly.", ) diff --git a/src/schema/schema.ts b/src/schema/schema.ts index e5ddaafcc..555483fb8 100644 --- a/src/schema/schema.ts +++ b/src/schema/schema.ts @@ -201,8 +201,7 @@ export class SchemaModule { * ```ts * await db.schema * .alterTable('person') - * .alterColumn('first_name') - * .setDataType('text') + * .alterColumn('first_name', (ac) => ac.setDataType('text')) * .execute() * ``` */ @@ -318,7 +317,7 @@ export class SchemaModule { */ withSchema(schema: string): SchemaModule { return new SchemaModule( - this.#executor.withPluginAtFront(new WithSchemaPlugin(schema)) + this.#executor.withPluginAtFront(new WithSchemaPlugin(schema)), ) } } diff --git a/src/schema/unique-constraint-builder.ts b/src/schema/unique-constraint-builder.ts new file mode 100644 index 000000000..324263098 --- /dev/null +++ b/src/schema/unique-constraint-builder.ts @@ -0,0 +1,35 @@ +import { OperationNodeSource } from '../operation-node/operation-node-source.js' +import { UniqueConstraintNode } from '../operation-node/unique-constraint-node.js' +import { preventAwait } from '../util/prevent-await.js' + +export class UniqueConstraintNodeBuilder implements OperationNodeSource { + readonly #node: UniqueConstraintNode + + constructor(node: UniqueConstraintNode) { + this.#node = node + } + + toOperationNode(): UniqueConstraintNode { + return this.#node + } + + /** + * Adds `nulls not distinct` to the unique constraint definition + * + * Supported by PostgreSQL dialect only + */ + nullsNotDistinct(): UniqueConstraintNodeBuilder { + return new UniqueConstraintNodeBuilder( + UniqueConstraintNode.cloneWith(this.#node, { nullsNotDistinct: true }), + ) + } +} + +preventAwait( + UniqueConstraintNodeBuilder, + "don't await UniqueConstraintNodeBuilder instances directly.", +) + +export type UniqueConstraintNodeBuilderCallback = ( + builder: UniqueConstraintNodeBuilder, +) => UniqueConstraintNodeBuilder diff --git a/src/util/assert.ts b/src/util/assert.ts index 8c51f5932..877bd69fd 100644 --- a/src/util/assert.ts +++ b/src/util/assert.ts @@ -1,5 +1,5 @@ export function assertNotNullOrUndefined( - value: T + value: T, ): asserts value is NonNullable { if (value === null || value === undefined) { throw new Error(`${value} must not be null or undefined`) diff --git a/src/util/column-type.ts b/src/util/column-type.ts index 0b0ff0fca..c8614bd05 100644 --- a/src/util/column-type.ts +++ b/src/util/column-type.ts @@ -1,3 +1,5 @@ +import { DrainOuterGeneric } from './type-utils.js' + /** * This type can be used to specify a different type for * select, insert and update operations. @@ -36,7 +38,7 @@ export type ColumnType< SelectType, InsertType = SelectType, - UpdateType = SelectType + UpdateType = SelectType, > = { readonly __select__: SelectType readonly __insert__: InsertType @@ -65,6 +67,16 @@ export type Generated = ColumnType */ export type GeneratedAlways = ColumnType +/** + * A shortcut for defining JSON columns, which are by default inserted/updated + * as stringified JSON strings. + */ +export type JSONColumnType< + SelectType extends object | null, + InsertType = string, + UpdateType = string, +> = ColumnType + /** * Evaluates to `K` if `T` can be `null` or `undefined`. */ @@ -76,10 +88,10 @@ type IfNullable = undefined extends T ? K : null extends T ? K : never type IfNotNullable = undefined extends T ? never : null extends T - ? never - : T extends never - ? never - : K + ? never + : T extends never + ? never + : K /** * Evaluates to `K` if `T` isn't `never`. @@ -139,9 +151,9 @@ export type UpdateKeys = { * // } * ``` */ -export type Selectable = { +export type Selectable = DrainOuterGeneric<{ [K in NonNeverSelectKeys]: SelectType -} +}> /** * Given a table interface, extracts the insert type from all @@ -164,11 +176,13 @@ export type Selectable = { * // } * ``` */ -export type Insertable = { - [K in NonNullableInsertKeys]: InsertType -} & { - [K in NullableInsertKeys]?: InsertType -} +export type Insertable = DrainOuterGeneric< + { + [K in NonNullableInsertKeys]: InsertType + } & { + [K in NullableInsertKeys]?: InsertType + } +> /** * Given a table interface, extracts the update type from all @@ -190,6 +204,6 @@ export type Insertable = { * // } * ``` */ -export type Updateable = { +export type Updateable = DrainOuterGeneric<{ [K in UpdateKeys]?: UpdateType -} +}> diff --git a/src/util/explainable.ts b/src/util/explainable.ts index ed2155895..95ef4f22b 100644 --- a/src/util/explainable.ts +++ b/src/util/explainable.ts @@ -46,6 +46,6 @@ export interface Explainable { */ explain = Record>( format?: ExplainFormat, - options?: Expression + options?: Expression, ): Promise } diff --git a/src/util/infer-result.ts b/src/util/infer-result.ts index 5e2e04858..d972bbe9d 100644 --- a/src/util/infer-result.ts +++ b/src/util/infer-result.ts @@ -1,8 +1,10 @@ import { DeleteResult } from '../query-builder/delete-result.js' import { InsertResult } from '../query-builder/insert-result.js' +import { MergeResult } from '../query-builder/merge-result.js' import { UpdateResult } from '../query-builder/update-result.js' import { CompiledQuery } from '../query-compiler/compiled-query.js' import { Compilable } from './compilable.js' +import { Simplify } from './type-utils.js' /** * A helper type that allows inferring a select/insert/update/delete query's result @@ -46,9 +48,13 @@ export type InferResult | CompiledQuery> = C extends Compilable ? ResolveResult : C extends CompiledQuery - ? ResolveResult - : never + ? ResolveResult + : never -type ResolveResult = O extends InsertResult | UpdateResult | DeleteResult +type ResolveResult = O extends + | InsertResult + | UpdateResult + | DeleteResult + | MergeResult ? O - : O[] + : Simplify[] diff --git a/src/util/json-object-args.ts b/src/util/json-object-args.ts new file mode 100644 index 000000000..7d2b058c6 --- /dev/null +++ b/src/util/json-object-args.ts @@ -0,0 +1,43 @@ +import { ExpressionWrapper } from '../expression/expression-wrapper.js' +import { Expression } from '../expression/expression.js' +import { AliasNode } from '../operation-node/alias-node.js' +import { ColumnNode } from '../operation-node/column-node.js' +import { IdentifierNode } from '../operation-node/identifier-node.js' +import { ReferenceNode } from '../operation-node/reference-node.js' +import { SelectQueryNode } from '../operation-node/select-query-node.js' +import { TableNode } from '../operation-node/table-node.js' +import { ValueNode } from '../operation-node/value-node.js' + +export function getJsonObjectArgs( + node: SelectQueryNode, + table: string, +): Expression[] { + const args: Expression[] = [] + + for (const { selection: s } of node.selections ?? []) { + if (ReferenceNode.is(s) && ColumnNode.is(s.column)) { + args.push( + colName(s.column.column.name), + colRef(table, s.column.column.name), + ) + } else if (ColumnNode.is(s)) { + args.push(colName(s.column.name), colRef(table, s.column.name)) + } else if (AliasNode.is(s) && IdentifierNode.is(s.alias)) { + args.push(colName(s.alias.name), colRef(table, s.alias.name)) + } else { + throw new Error(`can't extract column names from the select query node`) + } + } + + return args +} + +function colName(col: string): Expression { + return new ExpressionWrapper(ValueNode.createImmediate(col)) +} + +function colRef(table: string, col: string): Expression { + return new ExpressionWrapper( + ReferenceNode.create(ColumnNode.create(col), TableNode.create(table)), + ) +} diff --git a/src/util/log.ts b/src/util/log.ts index 8191e3cfd..2a3605b77 100644 --- a/src/util/log.ts +++ b/src/util/log.ts @@ -66,13 +66,19 @@ function defaultLogger(event: LogEvent): void { if (event.level === 'query') { console.log(`kysely:query: ${event.query.sql}`) console.log( - `kysely:query: duration: ${event.queryDurationMillis.toFixed(1)}ms` + `kysely:query: duration: ${event.queryDurationMillis.toFixed(1)}ms`, ) } else if (event.level === 'error') { if (event.error instanceof Error) { console.error(`kysely:error: ${event.error.stack ?? event.error.message}`) } else { - console.error(`kysely:error: ${event}`) + console.error( + `kysely:error: ${JSON.stringify({ + error: event.error, + query: event.query.sql, + queryDurationMillis: event.queryDurationMillis, + })}`, + ) } } } diff --git a/src/util/object-utils.ts b/src/util/object-utils.ts index f26983652..845f9ee87 100644 --- a/src/util/object-utils.ts +++ b/src/util/object-utils.ts @@ -34,7 +34,7 @@ export function isDate(obj: unknown): obj is Date { return obj instanceof Date } -export function isBigInt(obj: unknown): obj is BigInt { +export function isBigInt(obj: unknown): obj is bigint { return typeof obj === 'bigint' } @@ -53,11 +53,21 @@ export function isObject(obj: unknown): obj is ShallowRecord { } export function isArrayBufferOrView( - obj: unknown + obj: unknown, ): obj is ArrayBuffer | ArrayBufferView { return obj instanceof ArrayBuffer || ArrayBuffer.isView(obj) } +export function isPlainObject(obj: unknown): obj is Record { + return ( + isObject(obj) && + !Array.isArray(obj) && + !isDate(obj) && + !isBuffer(obj) && + !isArrayBufferOrView(obj) + ) +} + export function getLast(arr: ArrayLike): T | undefined { return arr[arr.length - 1] } @@ -66,8 +76,8 @@ export function freeze(obj: T): Readonly { return Object.freeze(obj) } -export function asArray(arg: T | T[]): T[] { - if (Array.isArray(arg)) { +export function asArray(arg: T | ReadonlyArray): ReadonlyArray { + if (isReadonlyArray(arg)) { return arg } else { return [arg] @@ -75,7 +85,7 @@ export function asArray(arg: T | T[]): T[] { } export function asReadonlyArray( - arg: T | ReadonlyArray + arg: T | ReadonlyArray, ): ReadonlyArray { if (isReadonlyArray(arg)) { return arg @@ -104,7 +114,7 @@ export function compare(obj1: unknown, obj2: unknown): boolean { function compareArrays( arr1: ReadonlyArray, - arr2: ReadonlyArray + arr2: ReadonlyArray, ): boolean { if (arr1.length !== arr2.length) { return false @@ -121,7 +131,7 @@ function compareArrays( function compareObjects( obj1: Record, - obj2: Record + obj2: Record, ): boolean { if (isBuffer(obj1) && isBuffer(obj2)) { return compareBuffers(obj1, obj2) @@ -142,7 +152,7 @@ function compareDates(date1: Date, date2: Date) { function compareGenericObjects( obj1: Record, - obj2: Record + obj2: Record, ): boolean { const keys1 = Object.keys(obj1) const keys2 = Object.keys(obj2) diff --git a/src/util/type-utils.ts b/src/util/type-utils.ts index 492b140a0..1e0aee3a3 100644 --- a/src/util/type-utils.ts +++ b/src/util/type-utils.ts @@ -1,8 +1,8 @@ -import { SelectQueryBuilder } from '../query-builder/select-query-builder.js' import { InsertResult } from '../query-builder/insert-result.js' import { DeleteResult } from '../query-builder/delete-result.js' import { UpdateResult } from '../query-builder/update-result.js' import { KyselyTypeError } from './type-error.js' +import { MergeResult } from '../query-builder/merge-result.js' /** * Given a database type and a union of table names in that db, returns @@ -35,12 +35,10 @@ import { KyselyTypeError } from './type-error.js' * // Columns == 'id' | 'name' | 'species' * ``` */ -export type AnyColumn = DrainOuterGeneric< - { - [T in TB]: keyof DB[T] - }[TB] & - string -> +export type AnyColumn = { + [T in TB]: keyof DB[T] +}[TB] & + string /** * Extracts a column type. @@ -81,60 +79,49 @@ export type ExtractColumnType = { * ``` */ export type AnyColumnWithTable = { - [T in TB]: T extends string - ? keyof DB[T] extends string - ? `${T}.${keyof DB[T]}` - : never - : never + [T in TB]: `${T & string}.${keyof DB[T] & string}` }[TB] /** * Just like {@link AnyColumn} but with a ` as ` suffix. */ -export type AnyAliasedColumn = { - [T in TB]: T extends string - ? keyof DB[T] extends string - ? `${keyof DB[T]} as ${string}` - : never - : never -}[TB] +export type AnyAliasedColumn = `${AnyColumn< + DB, + TB +>} as ${string}` /** * Just like {@link AnyColumnWithTable} but with a ` as ` suffix. */ -export type AnyAliasedColumnWithTable = { - [T in TB]: T extends string - ? keyof DB[T] extends string - ? `${T}.${keyof DB[T]} as ${string}` - : never - : never -}[TB] +export type AnyAliasedColumnWithTable< + DB, + TB extends keyof DB, +> = `${AnyColumnWithTable} as ${string}` /** * Extracts the item type of an array. */ export type ArrayItemType = T extends ReadonlyArray ? I : never -/** - * Any select query builder. - */ -export type AnySelectQueryBuilder = SelectQueryBuilder - export type SimplifySingleResult = O extends InsertResult ? O : O extends DeleteResult - ? O - : O extends UpdateResult - ? O - : Simplify | undefined + ? O + : O extends UpdateResult + ? O + : O extends MergeResult + ? O + : Simplify | undefined export type SimplifyResult = O extends InsertResult ? O : O extends DeleteResult - ? O - : O extends UpdateResult - ? O - : Simplify + ? O + : O extends UpdateResult + ? O + : O extends MergeResult + ? O + : Simplify export type Simplify = DrainOuterGeneric<{ [K in keyof T]: T[K] } & {}> @@ -162,18 +149,39 @@ export type IsAny = 0 extends T & 1 ? true : false * Evaluates to `true` if the types `T` and `U` are equal. */ export type Equals = (() => G extends T ? 1 : 2) extends < - G + G, >() => G extends U ? 1 : 2 ? true : false -export type NarrowPartial = DrainOuterGeneric<{ - [K in keyof S & string]: K extends keyof T - ? T[K] extends S[K] - ? T[K] - : KyselyTypeError<`$narrowType() call failed: passed type does not exist in '${K}'s type union`> - : S[K] -}> +export type NarrowPartial = DrainOuterGeneric< + T extends object + ? { + [K in keyof O & string]: K extends keyof T + ? T[K] extends NotNull + ? Exclude + : T[K] extends O[K] + ? T[K] + : KyselyTypeError<`$narrowType() call failed: passed type does not exist in '${K}'s type union`> + : O[K] + } + : never +> + +/** + * A type constant for marking a column as not null. Can be used with `$narrowPartial`. + * + * Example: + * + * ```ts + * const person = await db.selectFrom('person') + * .where('nullable_column', 'is not', null) + * .selectAll() + * .$narrowType<{ nullable_column: NotNull }>() + * .executeTakeFirstOrThrow() + * ``` + */ +export type NotNull = { readonly __notNull__: unique symbol } export type SqlBool = boolean | 0 | 1 diff --git a/test/bun/bun.lockb b/test/bun/bun.lockb new file mode 100644 index 000000000..e716655b7 Binary files /dev/null and b/test/bun/bun.lockb differ diff --git a/test/bun/bun.test.ts b/test/bun/bun.test.ts new file mode 100644 index 000000000..9becba23d --- /dev/null +++ b/test/bun/bun.test.ts @@ -0,0 +1,62 @@ +import { createPool } from 'mysql2' +import { Pool } from 'pg' +import { + Generated, + Kysely, + PostgresDialect, + MysqlDialect, + sql, +} from '../../dist/esm/index.js' + +interface Person { + id: Generated + first_name: string + last_name: string | null +} + +interface Database { + person: Person +} + +const dbs = [ + new Kysely({ + dialect: new PostgresDialect({ + pool: new Pool({ + database: 'kysely_test', + host: 'localhost', + user: 'kysely', + port: 5434, + }), + }), + }), + new Kysely({ + dialect: new MysqlDialect({ + pool: createPool({ + database: 'kysely_test', + host: 'localhost', + user: 'kysely', + password: 'kysely', + port: 3308, + }), + }), + }), +] + +if ( + dbs + .map((db) => db.selectFrom('person').select('id').compile().sql) + .some( + (sql) => sql.match(/^select ["`]id["`] from ["`]person["`]$/) === null, + ) +) { + console.error('bun test failed') + process.exit(1) +} + +const query = sql`select 1` + +await Promise.all(dbs.map((db) => query.execute(db))) + +console.log('bun test passed') + +await Promise.all(dbs.map((db) => db.destroy())) diff --git a/test/bun/package.json b/test/bun/package.json new file mode 100644 index 000000000..08285b44f --- /dev/null +++ b/test/bun/package.json @@ -0,0 +1,12 @@ +{ + "name": "kysely-bun-test", + "private": true, + "scripts": { + "test": "bun bun.test.ts" + }, + "dependencies": { + "kysely": "^0.25.0", + "mysql2": "^3.3.3", + "pg": "^8.11.0" + } +} diff --git a/test/cloudflare-workers/.dev.vars b/test/cloudflare-workers/.dev.vars new file mode 100644 index 000000000..e69de29bb diff --git a/test/cloudflare-workers/api.ts b/test/cloudflare-workers/api.ts new file mode 100644 index 000000000..0480f5764 --- /dev/null +++ b/test/cloudflare-workers/api.ts @@ -0,0 +1,43 @@ +import { Pool } from 'pg' +import { Hono } from 'hono' +import { Generated, Kysely, PostgresDialect, sql } from '../../' + +interface Person { + id: Generated + first_name: string + last_name: string | null +} + +interface Database { + person: Person +} + +const db = new Kysely({ + dialect: new PostgresDialect({ + pool: new Pool({ + database: 'kysely_test', + host: 'localhost', + user: 'kysely', + port: 5434, + }), + }), +}) + +const app = new Hono() + +app.get('/', async (c) => { + if ( + db.selectFrom('person').selectAll().compile().sql !== + 'select * from "person"' + ) { + throw new Error('Unexpected SQL') + } + + const { + rows: [row], + } = await sql`select 1 as ok`.execute(db) + + return c.json(row) +}) + +export default app diff --git a/test/cloudflare-workers/package-lock.json b/test/cloudflare-workers/package-lock.json new file mode 100644 index 000000000..774938f08 --- /dev/null +++ b/test/cloudflare-workers/package-lock.json @@ -0,0 +1,3457 @@ +{ + "name": "kysely-cloudflare-workers-test", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "kysely-cloudflare-workers-test", + "devDependencies": { + "hono": "^3.2.7", + "tsx": "^3.12.7", + "wrangler": "^3.1.2" + } + }, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.2.0.tgz", + "integrity": "sha512-MVbXLbTcAotOPUj0pAMhVtJ+3/kFkwJqc5qNOleOZTv6QkZZABDMS21dSrSlVswEHwrpWC03e4fWytjqKvuE2A==", + "dev": true, + "dependencies": { + "mime": "^3.0.0" + } + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20230628.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20230628.0.tgz", + "integrity": "sha512-ndtsGCR3WKcNvq2eE2teQXcE+r7PwMh3jnyxPuc4/Fed4q3DQC++da4zNn8f+D+dLd7myifGeygbHic86vh4OA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20230628.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20230628.0.tgz", + "integrity": "sha512-cvGUkP517K43PzlMm0Q9WFBJCOC8UR+E5qNf+nO2fewAx8SCyeqrOboVliDBaQmI8z6F6f59L6Gh4QuxEJEjdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20230628.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20230628.0.tgz", + "integrity": "sha512-NRYVNTuhvAxBzkj3V1TkYl1LiV9xxT6yk3OUXzcA6eUPH2EQYkDeOkWhAeuKrTi5JY8gLUvvxs5OOj5WTL9jYQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20230628.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20230628.0.tgz", + "integrity": "sha512-IVrP/Pf12k9S31TDjnHSUe/xrYLkuvQN+DtoUSWVgpe0Mj1w8uHUPGpRIc8XQF+6OWFUQr2SgGsEtjeYZm3Hlw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20230628.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20230628.0.tgz", + "integrity": "sha512-y6scWqHFHhlf2a1AsT0UeMyWSloIO1baVxp9DW62gFO8BwWrTPgwiG9Rr09zllY5tSxkrU7VOPsEbK9NNcRMsA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@esbuild-kit/cjs-loader": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.2.tgz", + "integrity": "sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==", + "dev": true, + "dependencies": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "node_modules/@esbuild-kit/core-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.1.0.tgz", + "integrity": "sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw==", + "dev": true, + "dependencies": { + "esbuild": "~0.17.6", + "source-map-support": "^0.5.21" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild-kit/core-utils/node_modules/esbuild": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", + "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.17.19", + "@esbuild/android-arm64": "0.17.19", + "@esbuild/android-x64": "0.17.19", + "@esbuild/darwin-arm64": "0.17.19", + "@esbuild/darwin-x64": "0.17.19", + "@esbuild/freebsd-arm64": "0.17.19", + "@esbuild/freebsd-x64": "0.17.19", + "@esbuild/linux-arm": "0.17.19", + "@esbuild/linux-arm64": "0.17.19", + "@esbuild/linux-ia32": "0.17.19", + "@esbuild/linux-loong64": "0.17.19", + "@esbuild/linux-mips64el": "0.17.19", + "@esbuild/linux-ppc64": "0.17.19", + "@esbuild/linux-riscv64": "0.17.19", + "@esbuild/linux-s390x": "0.17.19", + "@esbuild/linux-x64": "0.17.19", + "@esbuild/netbsd-x64": "0.17.19", + "@esbuild/openbsd-x64": "0.17.19", + "@esbuild/sunos-x64": "0.17.19", + "@esbuild/win32-arm64": "0.17.19", + "@esbuild/win32-ia32": "0.17.19", + "@esbuild/win32-x64": "0.17.19" + } + }, + "node_modules/@esbuild-kit/esm-loader": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.5.tgz", + "integrity": "sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==", + "dev": true, + "dependencies": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "node_modules/@esbuild-plugins/node-globals-polyfill": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.1.1.tgz", + "integrity": "sha512-MR0oAA+mlnJWrt1RQVQ+4VYuRJW/P2YmRTv1AsplObyvuBMnPHiizUF95HHYiSsMGLhyGtWufaq2XQg6+iurBg==", + "dev": true, + "peerDependencies": { + "esbuild": "*" + } + }, + "node_modules/@esbuild-plugins/node-modules-polyfill": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.1.4.tgz", + "integrity": "sha512-uZbcXi0zbmKC/050p3gJnne5Qdzw8vkXIv+c2BW0Lsc1ji1SkrxbKPUy5Efr0blbTu1SL8w4eyfpnSdPg3G0Qg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^4.0.0", + "rollup-plugin-node-polyfills": "^0.2.1" + }, + "peerDependencies": { + "esbuild": "*" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.3.tgz", + "integrity": "sha512-mueuEoh+s1eRbSJqq9KNBQwI4QhQV6sRXIfTyLXSHGMpyew61rOK4qY21uKbXl1iBoMb0AdL1deWFCQVlN2qHA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.3.tgz", + "integrity": "sha512-RolFVeinkeraDvN/OoRf1F/lP0KUfGNb5jxy/vkIMeRRChkrX/HTYN6TYZosRJs3a1+8wqpxAo5PI5hFmxyPRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.3.tgz", + "integrity": "sha512-SFpTUcIT1bIJuCCBMCQWq1bL2gPTjWoLZdjmIhjdcQHaUfV41OQfho6Ici5uvvkMmZRXIUGpM3GxysP/EU7ifQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.3.tgz", + "integrity": "sha512-DO8WykMyB+N9mIDfI/Hug70Dk1KipavlGAecxS3jDUwAbTpDXj0Lcwzw9svkhxfpCagDmpaTMgxWK8/C/XcXvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.3.tgz", + "integrity": "sha512-uEqZQ2omc6BvWqdCiyZ5+XmxuHEi1SPzpVxXCSSV2+Sh7sbXbpeNhHIeFrIpRjAs0lI1FmA1iIOxFozKBhKgRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.3.tgz", + "integrity": "sha512-nJansp3sSXakNkOD5i5mIz2Is/HjzIhFs49b1tjrPrpCmwgBmH9SSzhC/Z1UqlkivqMYkhfPwMw1dGFUuwmXhw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.3.tgz", + "integrity": "sha512-TfoDzLw+QHfc4a8aKtGSQ96Wa+6eimljjkq9HKR0rHlU83vw8aldMOUSJTUDxbcUdcgnJzPaX8/vGWm7vyV7ug==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.3.tgz", + "integrity": "sha512-VwswmSYwVAAq6LysV59Fyqk3UIjbhuc6wb3vEcJ7HEJUtFuLK9uXWuFoH1lulEbE4+5GjtHi3MHX+w1gNHdOWQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.3.tgz", + "integrity": "sha512-7I3RlsnxEFCHVZNBLb2w7unamgZ5sVwO0/ikE2GaYvYuUQs9Qte/w7TqWcXHtCwxvZx/2+F97ndiUQAWs47ZfQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.3.tgz", + "integrity": "sha512-X8FDDxM9cqda2rJE+iblQhIMYY49LfvW4kaEjoFbTTQ4Go8G96Smj2w3BRTwA8IHGoi9dPOPGAX63dhuv19UqA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.3.tgz", + "integrity": "sha512-hIbeejCOyO0X9ujfIIOKjBjNAs9XD/YdJ9JXAy1lHA+8UXuOqbFe4ErMCqMr8dhlMGBuvcQYGF7+kO7waj2KHw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.3.tgz", + "integrity": "sha512-znFRzICT/V8VZQMt6rjb21MtAVJv/3dmKRMlohlShrbVXdBuOdDrGb+C2cZGQAR8RFyRe7HS6klmHq103WpmVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.3.tgz", + "integrity": "sha512-EV7LuEybxhXrVTDpbqWF2yehYRNz5e5p+u3oQUS2+ZFpknyi1NXxr8URk4ykR8Efm7iu04//4sBg249yNOwy5Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.3.tgz", + "integrity": "sha512-uDxqFOcLzFIJ+r/pkTTSE9lsCEaV/Y6rMlQjUI9BkzASEChYL/aSQjZjchtEmdnVxDKETnUAmsaZ4pqK1eE5BQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.3.tgz", + "integrity": "sha512-NbeREhzSxYwFhnCAQOQZmajsPYtX71Ufej3IQ8W2Gxskfz9DK58ENEju4SbpIj48VenktRASC52N5Fhyf/aliQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.3.tgz", + "integrity": "sha512-SDiG0nCixYO9JgpehoKgScwic7vXXndfasjnD5DLbp1xltANzqZ425l7LSdHynt19UWOcDjG9wJJzSElsPvk0w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.3.tgz", + "integrity": "sha512-AzbsJqiHEq1I/tUvOfAzCY15h4/7Ivp3ff/o1GpP16n48JMNAtbW0qui2WCgoIZArEHD0SUQ95gvR0oSO7ZbdA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.3.tgz", + "integrity": "sha512-gSABi8qHl8k3Cbi/4toAzHiykuBuWLZs43JomTcXkjMZVkp0gj3gg9mO+9HJW/8GB5H89RX/V0QP4JGL7YEEVg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.3.tgz", + "integrity": "sha512-SF9Kch5Ete4reovvRO6yNjMxrvlfT0F0Flm+NPoUw5Z4Q3r1d23LFTgaLwm3Cp0iGbrU/MoUI+ZqwCv5XJijCw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.3.tgz", + "integrity": "sha512-u5aBonZIyGopAZyOnoPAA6fGsDeHByZ9CnEzyML9NqntK6D/xl5jteZUKm/p6nD09+v3pTM6TuUIqSPcChk5gg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.3.tgz", + "integrity": "sha512-GlgVq1WpvOEhNioh74TKelwla9KDuAaLZrdxuuUgsP2vayxeLgVc+rbpIv0IYF4+tlIzq2vRhofV+KGLD+37EQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.3.tgz", + "integrity": "sha512-5/JuTd8OWW8UzEtyf19fbrtMJENza+C9JoPIkvItgTBQ1FO2ZLvjbPO6Xs54vk0s5JB5QsfieUEshRQfu7ZHow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/as-table": { + "version": "1.0.55", + "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz", + "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==", + "dev": true, + "dependencies": { + "printable-characters": "^1.0.42" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/better-sqlite3": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.4.0.tgz", + "integrity": "sha512-NmsNW1CQvqMszu/CFAJ3pLct6NEFlNfuGM6vw72KHkjOD1UDnL96XNN1BMQc1hiHo8vE2GbOWQYIpZ+YM5wrZw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/capnp-ts": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/capnp-ts/-/capnp-ts-0.7.0.tgz", + "integrity": "sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==", + "dev": true, + "dependencies": { + "debug": "^4.3.1", + "tslib": "^2.2.0" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", + "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/esbuild": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.3.tgz", + "integrity": "sha512-71f7EjPWTiSguen8X/kxEpkAS7BFHwtQKisCDDV3Y4GLGWBaoSCyD5uXkaUew6JDzA9FEN1W23mdnSwW9kqCeg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.16.3", + "@esbuild/android-arm64": "0.16.3", + "@esbuild/android-x64": "0.16.3", + "@esbuild/darwin-arm64": "0.16.3", + "@esbuild/darwin-x64": "0.16.3", + "@esbuild/freebsd-arm64": "0.16.3", + "@esbuild/freebsd-x64": "0.16.3", + "@esbuild/linux-arm": "0.16.3", + "@esbuild/linux-arm64": "0.16.3", + "@esbuild/linux-ia32": "0.16.3", + "@esbuild/linux-loong64": "0.16.3", + "@esbuild/linux-mips64el": "0.16.3", + "@esbuild/linux-ppc64": "0.16.3", + "@esbuild/linux-riscv64": "0.16.3", + "@esbuild/linux-s390x": "0.16.3", + "@esbuild/linux-x64": "0.16.3", + "@esbuild/netbsd-x64": "0.16.3", + "@esbuild/openbsd-x64": "0.16.3", + "@esbuild/sunos-x64": "0.16.3", + "@esbuild/win32-arm64": "0.16.3", + "@esbuild/win32-ia32": "0.16.3", + "@esbuild/win32-x64": "0.16.3" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "node_modules/exit-hook": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-source": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz", + "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==", + "dev": true, + "dependencies": { + "data-uri-to-buffer": "^2.0.0", + "source-map": "^0.6.1" + } + }, + "node_modules/get-source/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.6.2.tgz", + "integrity": "sha512-E5XrT4CbbXcXWy+1jChlZmrmCwd5KGx502kDCXJJ7y898TtWW9FwoG5HfOLVRKmlmDGkWN2HM9Ho+/Y8F0sJDg==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/hono": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/hono/-/hono-3.2.7.tgz", + "integrity": "sha512-7YCF9t4oMF3L3ghvcmlEBx2hoC9VyBBLuVrPZiOkU7PtFBrnQtkFEnYCRcPKCJiMoXHX3bDhU9R3HQbw+WnQJg==", + "dev": true, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/miniflare": { + "version": "3.20230628.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20230628.0.tgz", + "integrity": "sha512-5tg+hWlY9kCZaJ8y1CA7Y1SuPOCjJWFthLLsJKX5Mj1KfUR96MHY2Hcboyk3KbzDiIWUd3eEIoEoriQ/H9egUw==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-walk": "^8.2.0", + "better-sqlite3": "^8.1.0", + "capnp-ts": "^0.7.0", + "exit-hook": "^2.2.1", + "glob-to-regexp": "^0.4.1", + "http-cache-semantics": "^4.1.0", + "kleur": "^4.1.5", + "set-cookie-parser": "^2.6.0", + "source-map-support": "0.5.21", + "stoppable": "^1.1.0", + "undici": "^5.13.0", + "workerd": "1.20230628.0", + "ws": "^8.11.0", + "youch": "^3.2.2", + "zod": "^3.20.6" + }, + "engines": { + "node": ">=16.13" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "dev": true, + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, + "node_modules/node-abi": { + "version": "3.45.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.45.0.tgz", + "integrity": "sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", + "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/printable-characters": { + "version": "1.0.42", + "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz", + "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rollup-plugin-inject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", + "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.", + "dev": true, + "dependencies": { + "estree-walker": "^0.6.1", + "magic-string": "^0.25.3", + "rollup-pluginutils": "^2.8.1" + } + }, + "node_modules/rollup-plugin-node-polyfills": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", + "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", + "dev": true, + "dependencies": { + "rollup-plugin-inject": "^3.0.0" + } + }, + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "dependencies": { + "estree-walker": "^0.6.1" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/selfsigned": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", + "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "dev": true, + "dependencies": { + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==", + "dev": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "dev": true + }, + "node_modules/stacktracey": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz", + "integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==", + "dev": true, + "dependencies": { + "as-table": "^1.0.36", + "get-source": "^2.0.12" + } + }, + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "dev": true, + "engines": { + "node": ">=4", + "npm": ">=6" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "dev": true + }, + "node_modules/tsx": { + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.7.tgz", + "integrity": "sha512-C2Ip+jPmqKd1GWVQDvz/Eyc6QJbGfE7NrR3fx5BpEHMZsEHoIxHL1j+lKdGobr8ovEyqeNkPLSKp6SCSOt7gmw==", + "dev": true, + "dependencies": { + "@esbuild-kit/cjs-loader": "^2.4.2", + "@esbuild-kit/core-utils": "^3.0.0", + "@esbuild-kit/esm-loader": "^2.5.5" + }, + "bin": { + "tsx": "dist/cli.js" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/undici": { + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", + "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", + "dev": true, + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/workerd": { + "version": "1.20230628.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20230628.0.tgz", + "integrity": "sha512-V4b+xfsBtogUmDa5yYWWROgTAVkKi09sqbT/2dBh1KhEuRgENScgo/VysTtZsX5Fmxd8qEo1phpNJeTC+DW1iA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20230628.0", + "@cloudflare/workerd-darwin-arm64": "1.20230628.0", + "@cloudflare/workerd-linux-64": "1.20230628.0", + "@cloudflare/workerd-linux-arm64": "1.20230628.0", + "@cloudflare/workerd-windows-64": "1.20230628.0" + } + }, + "node_modules/wrangler": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.1.2.tgz", + "integrity": "sha512-UvpKpemw2Bt0tSS3Dspkw0tp/d2dR3W3hdHjyM7jEsv+xgmQgEZqoN8gdA/2sgECO3FXRdLuQZDdcuOO43aHFw==", + "dev": true, + "dependencies": { + "@cloudflare/kv-asset-handler": "^0.2.0", + "@esbuild-plugins/node-globals-polyfill": "^0.1.1", + "@esbuild-plugins/node-modules-polyfill": "^0.1.4", + "blake3-wasm": "^2.1.5", + "chokidar": "^3.5.3", + "esbuild": "0.16.3", + "miniflare": "3.20230628.0", + "nanoid": "^3.3.3", + "path-to-regexp": "^6.2.0", + "selfsigned": "^2.0.1", + "source-map": "^0.7.4", + "xxhash-wasm": "^1.0.1" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=16.13.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xxhash-wasm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz", + "integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/youch": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/youch/-/youch-3.2.3.tgz", + "integrity": "sha512-ZBcWz/uzZaQVdCvfV4uk616Bbpf2ee+F/AvuKDR5EwX/Y4v06xWdtMluqTD7+KlZdM93lLm9gMZYo0sKBS0pgw==", + "dev": true, + "dependencies": { + "cookie": "^0.5.0", + "mustache": "^4.2.0", + "stacktracey": "^2.1.8" + } + }, + "node_modules/zod": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", + "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + }, + "dependencies": { + "@cloudflare/kv-asset-handler": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.2.0.tgz", + "integrity": "sha512-MVbXLbTcAotOPUj0pAMhVtJ+3/kFkwJqc5qNOleOZTv6QkZZABDMS21dSrSlVswEHwrpWC03e4fWytjqKvuE2A==", + "dev": true, + "requires": { + "mime": "^3.0.0" + } + }, + "@cloudflare/workerd-darwin-64": { + "version": "1.20230628.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20230628.0.tgz", + "integrity": "sha512-ndtsGCR3WKcNvq2eE2teQXcE+r7PwMh3jnyxPuc4/Fed4q3DQC++da4zNn8f+D+dLd7myifGeygbHic86vh4OA==", + "dev": true, + "optional": true + }, + "@cloudflare/workerd-darwin-arm64": { + "version": "1.20230628.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20230628.0.tgz", + "integrity": "sha512-cvGUkP517K43PzlMm0Q9WFBJCOC8UR+E5qNf+nO2fewAx8SCyeqrOboVliDBaQmI8z6F6f59L6Gh4QuxEJEjdA==", + "dev": true, + "optional": true + }, + "@cloudflare/workerd-linux-64": { + "version": "1.20230628.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20230628.0.tgz", + "integrity": "sha512-NRYVNTuhvAxBzkj3V1TkYl1LiV9xxT6yk3OUXzcA6eUPH2EQYkDeOkWhAeuKrTi5JY8gLUvvxs5OOj5WTL9jYQ==", + "dev": true, + "optional": true + }, + "@cloudflare/workerd-linux-arm64": { + "version": "1.20230628.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20230628.0.tgz", + "integrity": "sha512-IVrP/Pf12k9S31TDjnHSUe/xrYLkuvQN+DtoUSWVgpe0Mj1w8uHUPGpRIc8XQF+6OWFUQr2SgGsEtjeYZm3Hlw==", + "dev": true, + "optional": true + }, + "@cloudflare/workerd-windows-64": { + "version": "1.20230628.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20230628.0.tgz", + "integrity": "sha512-y6scWqHFHhlf2a1AsT0UeMyWSloIO1baVxp9DW62gFO8BwWrTPgwiG9Rr09zllY5tSxkrU7VOPsEbK9NNcRMsA==", + "dev": true, + "optional": true + }, + "@esbuild-kit/cjs-loader": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.2.tgz", + "integrity": "sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==", + "dev": true, + "requires": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "@esbuild-kit/core-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.1.0.tgz", + "integrity": "sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw==", + "dev": true, + "requires": { + "esbuild": "~0.17.6", + "source-map-support": "^0.5.21" + }, + "dependencies": { + "@esbuild/android-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "dev": true, + "optional": true + }, + "esbuild": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", + "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.17.19", + "@esbuild/android-arm64": "0.17.19", + "@esbuild/android-x64": "0.17.19", + "@esbuild/darwin-arm64": "0.17.19", + "@esbuild/darwin-x64": "0.17.19", + "@esbuild/freebsd-arm64": "0.17.19", + "@esbuild/freebsd-x64": "0.17.19", + "@esbuild/linux-arm": "0.17.19", + "@esbuild/linux-arm64": "0.17.19", + "@esbuild/linux-ia32": "0.17.19", + "@esbuild/linux-loong64": "0.17.19", + "@esbuild/linux-mips64el": "0.17.19", + "@esbuild/linux-ppc64": "0.17.19", + "@esbuild/linux-riscv64": "0.17.19", + "@esbuild/linux-s390x": "0.17.19", + "@esbuild/linux-x64": "0.17.19", + "@esbuild/netbsd-x64": "0.17.19", + "@esbuild/openbsd-x64": "0.17.19", + "@esbuild/sunos-x64": "0.17.19", + "@esbuild/win32-arm64": "0.17.19", + "@esbuild/win32-ia32": "0.17.19", + "@esbuild/win32-x64": "0.17.19" + } + } + } + }, + "@esbuild-kit/esm-loader": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.5.tgz", + "integrity": "sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==", + "dev": true, + "requires": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "@esbuild-plugins/node-globals-polyfill": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.1.1.tgz", + "integrity": "sha512-MR0oAA+mlnJWrt1RQVQ+4VYuRJW/P2YmRTv1AsplObyvuBMnPHiizUF95HHYiSsMGLhyGtWufaq2XQg6+iurBg==", + "dev": true, + "requires": {} + }, + "@esbuild-plugins/node-modules-polyfill": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.1.4.tgz", + "integrity": "sha512-uZbcXi0zbmKC/050p3gJnne5Qdzw8vkXIv+c2BW0Lsc1ji1SkrxbKPUy5Efr0blbTu1SL8w4eyfpnSdPg3G0Qg==", + "dev": true, + "requires": { + "escape-string-regexp": "^4.0.0", + "rollup-plugin-node-polyfills": "^0.2.1" + } + }, + "@esbuild/android-arm": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.3.tgz", + "integrity": "sha512-mueuEoh+s1eRbSJqq9KNBQwI4QhQV6sRXIfTyLXSHGMpyew61rOK4qY21uKbXl1iBoMb0AdL1deWFCQVlN2qHA==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.3.tgz", + "integrity": "sha512-RolFVeinkeraDvN/OoRf1F/lP0KUfGNb5jxy/vkIMeRRChkrX/HTYN6TYZosRJs3a1+8wqpxAo5PI5hFmxyPRg==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.3.tgz", + "integrity": "sha512-SFpTUcIT1bIJuCCBMCQWq1bL2gPTjWoLZdjmIhjdcQHaUfV41OQfho6Ici5uvvkMmZRXIUGpM3GxysP/EU7ifQ==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.3.tgz", + "integrity": "sha512-DO8WykMyB+N9mIDfI/Hug70Dk1KipavlGAecxS3jDUwAbTpDXj0Lcwzw9svkhxfpCagDmpaTMgxWK8/C/XcXvw==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.3.tgz", + "integrity": "sha512-uEqZQ2omc6BvWqdCiyZ5+XmxuHEi1SPzpVxXCSSV2+Sh7sbXbpeNhHIeFrIpRjAs0lI1FmA1iIOxFozKBhKgRQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.3.tgz", + "integrity": "sha512-nJansp3sSXakNkOD5i5mIz2Is/HjzIhFs49b1tjrPrpCmwgBmH9SSzhC/Z1UqlkivqMYkhfPwMw1dGFUuwmXhw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.3.tgz", + "integrity": "sha512-TfoDzLw+QHfc4a8aKtGSQ96Wa+6eimljjkq9HKR0rHlU83vw8aldMOUSJTUDxbcUdcgnJzPaX8/vGWm7vyV7ug==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.3.tgz", + "integrity": "sha512-VwswmSYwVAAq6LysV59Fyqk3UIjbhuc6wb3vEcJ7HEJUtFuLK9uXWuFoH1lulEbE4+5GjtHi3MHX+w1gNHdOWQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.3.tgz", + "integrity": "sha512-7I3RlsnxEFCHVZNBLb2w7unamgZ5sVwO0/ikE2GaYvYuUQs9Qte/w7TqWcXHtCwxvZx/2+F97ndiUQAWs47ZfQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.3.tgz", + "integrity": "sha512-X8FDDxM9cqda2rJE+iblQhIMYY49LfvW4kaEjoFbTTQ4Go8G96Smj2w3BRTwA8IHGoi9dPOPGAX63dhuv19UqA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.3.tgz", + "integrity": "sha512-hIbeejCOyO0X9ujfIIOKjBjNAs9XD/YdJ9JXAy1lHA+8UXuOqbFe4ErMCqMr8dhlMGBuvcQYGF7+kO7waj2KHw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.3.tgz", + "integrity": "sha512-znFRzICT/V8VZQMt6rjb21MtAVJv/3dmKRMlohlShrbVXdBuOdDrGb+C2cZGQAR8RFyRe7HS6klmHq103WpmVw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.3.tgz", + "integrity": "sha512-EV7LuEybxhXrVTDpbqWF2yehYRNz5e5p+u3oQUS2+ZFpknyi1NXxr8URk4ykR8Efm7iu04//4sBg249yNOwy5Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.3.tgz", + "integrity": "sha512-uDxqFOcLzFIJ+r/pkTTSE9lsCEaV/Y6rMlQjUI9BkzASEChYL/aSQjZjchtEmdnVxDKETnUAmsaZ4pqK1eE5BQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.3.tgz", + "integrity": "sha512-NbeREhzSxYwFhnCAQOQZmajsPYtX71Ufej3IQ8W2Gxskfz9DK58ENEju4SbpIj48VenktRASC52N5Fhyf/aliQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.3.tgz", + "integrity": "sha512-SDiG0nCixYO9JgpehoKgScwic7vXXndfasjnD5DLbp1xltANzqZ425l7LSdHynt19UWOcDjG9wJJzSElsPvk0w==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.3.tgz", + "integrity": "sha512-AzbsJqiHEq1I/tUvOfAzCY15h4/7Ivp3ff/o1GpP16n48JMNAtbW0qui2WCgoIZArEHD0SUQ95gvR0oSO7ZbdA==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.3.tgz", + "integrity": "sha512-gSABi8qHl8k3Cbi/4toAzHiykuBuWLZs43JomTcXkjMZVkp0gj3gg9mO+9HJW/8GB5H89RX/V0QP4JGL7YEEVg==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.3.tgz", + "integrity": "sha512-SF9Kch5Ete4reovvRO6yNjMxrvlfT0F0Flm+NPoUw5Z4Q3r1d23LFTgaLwm3Cp0iGbrU/MoUI+ZqwCv5XJijCw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.3.tgz", + "integrity": "sha512-u5aBonZIyGopAZyOnoPAA6fGsDeHByZ9CnEzyML9NqntK6D/xl5jteZUKm/p6nD09+v3pTM6TuUIqSPcChk5gg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.3.tgz", + "integrity": "sha512-GlgVq1WpvOEhNioh74TKelwla9KDuAaLZrdxuuUgsP2vayxeLgVc+rbpIv0IYF4+tlIzq2vRhofV+KGLD+37EQ==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.3.tgz", + "integrity": "sha512-5/JuTd8OWW8UzEtyf19fbrtMJENza+C9JoPIkvItgTBQ1FO2ZLvjbPO6Xs54vk0s5JB5QsfieUEshRQfu7ZHow==", + "dev": true, + "optional": true + }, + "acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "as-table": { + "version": "1.0.55", + "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz", + "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==", + "dev": true, + "requires": { + "printable-characters": "^1.0.42" + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "better-sqlite3": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.4.0.tgz", + "integrity": "sha512-NmsNW1CQvqMszu/CFAJ3pLct6NEFlNfuGM6vw72KHkjOD1UDnL96XNN1BMQc1hiHo8vE2GbOWQYIpZ+YM5wrZw==", + "dev": true, + "requires": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.0" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "requires": { + "streamsearch": "^1.1.0" + } + }, + "capnp-ts": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/capnp-ts/-/capnp-ts-0.7.0.tgz", + "integrity": "sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==", + "dev": true, + "requires": { + "debug": "^4.3.1", + "tslib": "^2.2.0" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true + }, + "data-uri-to-buffer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", + "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "requires": { + "mimic-response": "^3.1.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "esbuild": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.3.tgz", + "integrity": "sha512-71f7EjPWTiSguen8X/kxEpkAS7BFHwtQKisCDDV3Y4GLGWBaoSCyD5uXkaUew6JDzA9FEN1W23mdnSwW9kqCeg==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.16.3", + "@esbuild/android-arm64": "0.16.3", + "@esbuild/android-x64": "0.16.3", + "@esbuild/darwin-arm64": "0.16.3", + "@esbuild/darwin-x64": "0.16.3", + "@esbuild/freebsd-arm64": "0.16.3", + "@esbuild/freebsd-x64": "0.16.3", + "@esbuild/linux-arm": "0.16.3", + "@esbuild/linux-arm64": "0.16.3", + "@esbuild/linux-ia32": "0.16.3", + "@esbuild/linux-loong64": "0.16.3", + "@esbuild/linux-mips64el": "0.16.3", + "@esbuild/linux-ppc64": "0.16.3", + "@esbuild/linux-riscv64": "0.16.3", + "@esbuild/linux-s390x": "0.16.3", + "@esbuild/linux-x64": "0.16.3", + "@esbuild/netbsd-x64": "0.16.3", + "@esbuild/openbsd-x64": "0.16.3", + "@esbuild/sunos-x64": "0.16.3", + "@esbuild/win32-arm64": "0.16.3", + "@esbuild/win32-ia32": "0.16.3", + "@esbuild/win32-x64": "0.16.3" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "exit-hook": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", + "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", + "dev": true + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "get-source": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz", + "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==", + "dev": true, + "requires": { + "data-uri-to-buffer": "^2.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "get-tsconfig": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.6.2.tgz", + "integrity": "sha512-E5XrT4CbbXcXWy+1jChlZmrmCwd5KGx502kDCXJJ7y898TtWW9FwoG5HfOLVRKmlmDGkWN2HM9Ho+/Y8F0sJDg==", + "dev": true, + "requires": { + "resolve-pkg-maps": "^1.0.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "hono": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/hono/-/hono-3.2.7.tgz", + "integrity": "sha512-7YCF9t4oMF3L3ghvcmlEBx2hoC9VyBBLuVrPZiOkU7PtFBrnQtkFEnYCRcPKCJiMoXHX3bDhU9R3HQbw+WnQJg==", + "dev": true + }, + "http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true + }, + "miniflare": { + "version": "3.20230628.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20230628.0.tgz", + "integrity": "sha512-5tg+hWlY9kCZaJ8y1CA7Y1SuPOCjJWFthLLsJKX5Mj1KfUR96MHY2Hcboyk3KbzDiIWUd3eEIoEoriQ/H9egUw==", + "dev": true, + "requires": { + "acorn": "^8.8.0", + "acorn-walk": "^8.2.0", + "better-sqlite3": "^8.1.0", + "capnp-ts": "^0.7.0", + "exit-hook": "^2.2.1", + "glob-to-regexp": "^0.4.1", + "http-cache-semantics": "^4.1.0", + "kleur": "^4.1.5", + "set-cookie-parser": "^2.6.0", + "source-map-support": "0.5.21", + "stoppable": "^1.1.0", + "undici": "^5.13.0", + "workerd": "1.20230628.0", + "ws": "^8.11.0", + "youch": "^3.2.2", + "zod": "^3.20.6" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "dev": true + }, + "nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, + "node-abi": { + "version": "3.45.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.45.0.tgz", + "integrity": "sha512-iwXuFrMAcFVi/ZoZiqq8BzAdsLw9kxDfTC0HMyjXfSL/6CSDAGD5UmR7azrAgWV1zKYq7dUUMj4owusBWKLsiQ==", + "dev": true, + "requires": { + "semver": "^7.3.5" + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "prebuild-install": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", + "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "dev": true, + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "printable-characters": { + "version": "1.0.42", + "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz", + "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true + }, + "rollup-plugin-inject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", + "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1", + "magic-string": "^0.25.3", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-node-polyfills": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", + "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", + "dev": true, + "requires": { + "rollup-plugin-inject": "^3.0.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "selfsigned": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", + "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "dev": true, + "requires": { + "node-forge": "^1" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==", + "dev": true + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "stacktracey": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz", + "integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==", + "dev": true, + "requires": { + "as-table": "^1.0.36", + "get-source": "^2.0.12" + } + }, + "stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "dev": true + }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "dev": true + }, + "tsx": { + "version": "3.12.7", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.7.tgz", + "integrity": "sha512-C2Ip+jPmqKd1GWVQDvz/Eyc6QJbGfE7NrR3fx5BpEHMZsEHoIxHL1j+lKdGobr8ovEyqeNkPLSKp6SCSOt7gmw==", + "dev": true, + "requires": { + "@esbuild-kit/cjs-loader": "^2.4.2", + "@esbuild-kit/core-utils": "^3.0.0", + "@esbuild-kit/esm-loader": "^2.5.5", + "fsevents": "~2.3.2" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "undici": { + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", + "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", + "dev": true, + "requires": { + "busboy": "^1.6.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "workerd": { + "version": "1.20230628.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20230628.0.tgz", + "integrity": "sha512-V4b+xfsBtogUmDa5yYWWROgTAVkKi09sqbT/2dBh1KhEuRgENScgo/VysTtZsX5Fmxd8qEo1phpNJeTC+DW1iA==", + "dev": true, + "requires": { + "@cloudflare/workerd-darwin-64": "1.20230628.0", + "@cloudflare/workerd-darwin-arm64": "1.20230628.0", + "@cloudflare/workerd-linux-64": "1.20230628.0", + "@cloudflare/workerd-linux-arm64": "1.20230628.0", + "@cloudflare/workerd-windows-64": "1.20230628.0" + } + }, + "wrangler": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.1.2.tgz", + "integrity": "sha512-UvpKpemw2Bt0tSS3Dspkw0tp/d2dR3W3hdHjyM7jEsv+xgmQgEZqoN8gdA/2sgECO3FXRdLuQZDdcuOO43aHFw==", + "dev": true, + "requires": { + "@cloudflare/kv-asset-handler": "^0.2.0", + "@esbuild-plugins/node-globals-polyfill": "^0.1.1", + "@esbuild-plugins/node-modules-polyfill": "^0.1.4", + "blake3-wasm": "^2.1.5", + "chokidar": "^3.5.3", + "esbuild": "0.16.3", + "fsevents": "~2.3.2", + "miniflare": "3.20230628.0", + "nanoid": "^3.3.3", + "path-to-regexp": "^6.2.0", + "selfsigned": "^2.0.1", + "source-map": "^0.7.4", + "xxhash-wasm": "^1.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "dev": true, + "requires": {} + }, + "xxhash-wasm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz", + "integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "youch": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/youch/-/youch-3.2.3.tgz", + "integrity": "sha512-ZBcWz/uzZaQVdCvfV4uk616Bbpf2ee+F/AvuKDR5EwX/Y4v06xWdtMluqTD7+KlZdM93lLm9gMZYo0sKBS0pgw==", + "dev": true, + "requires": { + "cookie": "^0.5.0", + "mustache": "^4.2.0", + "stacktracey": "^2.1.8" + } + }, + "zod": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", + "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "dev": true + } + } +} diff --git a/test/cloudflare-workers/package.json b/test/cloudflare-workers/package.json new file mode 100644 index 000000000..092ccfb77 --- /dev/null +++ b/test/cloudflare-workers/package.json @@ -0,0 +1,12 @@ +{ + "name": "kysely-cloudflare-workers-test", + "private": true, + "scripts": { + "test": "tsx test.ts" + }, + "devDependencies": { + "hono": "^3.2.7", + "tsx": "^3.12.7", + "wrangler": "^3.1.2" + } +} diff --git a/test/cloudflare-workers/test.ts b/test/cloudflare-workers/test.ts new file mode 100644 index 000000000..ad6aaa8c6 --- /dev/null +++ b/test/cloudflare-workers/test.ts @@ -0,0 +1,30 @@ +import { unstable_dev } from 'wrangler' +;(async () => { + const worker = await unstable_dev('./api.ts', { + compatibilityDate: '2023-06-28', + experimental: { disableExperimentalWarning: true }, + local: true, + // logLevel: 'debug', + nodeCompat: true, + vars: { + NAME: 'cloudflare', + }, + }) + + let exitCode = 0 + + try { + const response = await worker.fetch('/') + + if (!response.ok) { + throw new Error(`Unexpected response: ${response.status}`) + } + + console.log('test successful!') + } catch (error) { + exitCode = 1 + } finally { + await worker.stop() + process.exit(exitCode) + } +})() diff --git a/test/deno/cdn.test.ts b/test/deno/cdn.test.ts index 92709ba1b..59db76899 100644 --- a/test/deno/cdn.test.ts +++ b/test/deno/cdn.test.ts @@ -1,11 +1,6 @@ -import { - DummyDriver, - Generated, - Kysely, - PostgresAdapter, - PostgresIntrospector, - PostgresQueryCompiler, -} from 'https://cdn.jsdelivr.net/npm/kysely@0.19.0/dist/esm/index.js' +import { Generated, Kysely, MysqlDialect, PostgresDialect, sql } from 'kysely' +import { createPool } from 'mysql2' +import Pool from 'pg-pool' interface Person { id: Generated @@ -17,29 +12,43 @@ interface Database { person: Person } -const db = new Kysely({ - dialect: { - createAdapter() { - return new PostgresAdapter() - }, - createDriver() { - return new DummyDriver() - }, - createIntrospector(db: Kysely) { - return new PostgresIntrospector(db) - }, - createQueryCompiler() { - return new PostgresQueryCompiler() - }, - }, -}) - -const query = db.selectFrom('person').select('id') -const sql = query.compile() - -if (sql.sql !== 'select "id" from "person"') { - console.error('deno test failed') +const dbs = [ + new Kysely({ + dialect: new PostgresDialect({ + pool: new Pool({ + database: 'kysely_test', + host: 'localhost', + user: 'kysely', + port: 5434, + }), + }), + }), + new Kysely({ + dialect: new MysqlDialect({ + pool: createPool({ + database: 'kysely_test', + host: 'localhost', + user: 'kysely', + password: 'kysely', + port: 3308, + }), + }), + }), +] + +if ( + dbs + .map((db) => db.selectFrom('person').select('id').compile().sql) + .some((sql) => sql.match(/^select ["`]id["`] from ["`]person["`]$/) == null) +) { + console.error('CDN deno test failed') Deno.exit(1) } +const query = sql`select 1` + +await Promise.all(dbs.map((db) => query.execute(db))) + console.error('CDN deno test passed') + +await Promise.all(dbs.map((db) => db.destroy())) diff --git a/test/deno/deno.json b/test/deno/deno.json new file mode 100644 index 000000000..a1756d907 --- /dev/null +++ b/test/deno/deno.json @@ -0,0 +1,8 @@ +{ + "imports": { + "kysely": "npm:kysely@^0.25.0", + "mysql2": "npm:mysql2@^3.3.3", + "pg": "npm:pg@^8.11.0", + "pg-pool": "npm:pg-pool@^3.6.0" + } +} diff --git a/test/deno/deno.lock b/test/deno/deno.lock new file mode 100644 index 000000000..6176d8b04 --- /dev/null +++ b/test/deno/deno.lock @@ -0,0 +1,165 @@ +{ + "version": "2", + "remote": {}, + "npm": { + "specifiers": { + "kysely@^0.25.0": "kysely@0.25.0", + "mysql2@^3.3.3": "mysql2@3.3.3", + "pg-pool@^3.6.0": "pg-pool@3.6.0_pg@8.11.0" + }, + "packages": { + "buffer-writer@2.0.0": { + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "dependencies": {} + }, + "denque@2.1.0": { + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "dependencies": {} + }, + "generate-function@2.3.1": { + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dependencies": { + "is-property": "is-property@1.0.2" + } + }, + "iconv-lite@0.6.3": { + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": "safer-buffer@2.1.2" + } + }, + "is-property@1.0.2": { + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "dependencies": {} + }, + "kysely@0.25.0": { + "integrity": "sha512-srn0efIMu5IoEBk0tBmtGnoUss4uwvxtbFQWG/U2MosfqIace1l43IFP1PmEpHRDp+Z79xIcKEqmHH3dAvQdQA==", + "dependencies": {} + }, + "long@5.2.3": { + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", + "dependencies": {} + }, + "lru-cache@7.18.3": { + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dependencies": {} + }, + "lru-cache@8.0.5": { + "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", + "dependencies": {} + }, + "mysql2@3.3.3": { + "integrity": "sha512-MxDQJztArk4JFX1PKVjDhIXRzAmVJfuqZrVU+my6NeYBAA/XZRaDw5q7vga8TNvgyy3Lv3rivBFBBuJFbsdjaw==", + "dependencies": { + "denque": "denque@2.1.0", + "generate-function": "generate-function@2.3.1", + "iconv-lite": "iconv-lite@0.6.3", + "long": "long@5.2.3", + "lru-cache": "lru-cache@8.0.5", + "named-placeholders": "named-placeholders@1.1.3", + "seq-queue": "seq-queue@0.0.5", + "sqlstring": "sqlstring@2.3.3" + } + }, + "named-placeholders@1.1.3": { + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "dependencies": { + "lru-cache": "lru-cache@7.18.3" + } + }, + "packet-reader@1.0.0": { + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==", + "dependencies": {} + }, + "pg-cloudflare@1.1.0": { + "integrity": "sha512-tGM8/s6frwuAIyRcJ6nWcIvd3+3NmUKIs6OjviIm1HPPFEt5MzQDOTBQyhPWg/m0kCl95M6gA1JaIXtS8KovOA==", + "dependencies": {} + }, + "pg-connection-string@2.6.0": { + "integrity": "sha512-x14ibktcwlHKoHxx9X3uTVW9zIGR41ZB6QNhHb21OPNdCCO3NaRnpJuwKIQSR4u+Yqjx4HCvy7Hh7VSy1U4dGg==", + "dependencies": {} + }, + "pg-int8@1.0.1": { + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "dependencies": {} + }, + "pg-pool@3.6.0_pg@8.11.0": { + "integrity": "sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==", + "dependencies": { + "pg": "pg@8.11.0" + } + }, + "pg-protocol@1.6.0": { + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==", + "dependencies": {} + }, + "pg-types@2.2.0": { + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "pg-int8@1.0.1", + "postgres-array": "postgres-array@2.0.0", + "postgres-bytea": "postgres-bytea@1.0.0", + "postgres-date": "postgres-date@1.0.7", + "postgres-interval": "postgres-interval@1.2.0" + } + }, + "pg@8.11.0": { + "integrity": "sha512-meLUVPn2TWgJyLmy7el3fQQVwft4gU5NGyvV0XbD41iU9Jbg8lCH4zexhIkihDzVHJStlt6r088G6/fWeNjhXA==", + "dependencies": { + "buffer-writer": "buffer-writer@2.0.0", + "packet-reader": "packet-reader@1.0.0", + "pg-cloudflare": "pg-cloudflare@1.1.0", + "pg-connection-string": "pg-connection-string@2.6.0", + "pg-pool": "pg-pool@3.6.0_pg@8.11.0", + "pg-protocol": "pg-protocol@1.6.0", + "pg-types": "pg-types@2.2.0", + "pgpass": "pgpass@1.0.5" + } + }, + "pgpass@1.0.5": { + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "split2@4.2.0" + } + }, + "postgres-array@2.0.0": { + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "dependencies": {} + }, + "postgres-bytea@1.0.0": { + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "dependencies": {} + }, + "postgres-date@1.0.7": { + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "dependencies": {} + }, + "postgres-interval@1.2.0": { + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "xtend@4.0.2" + } + }, + "safer-buffer@2.1.2": { + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dependencies": {} + }, + "seq-queue@0.0.5": { + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==", + "dependencies": {} + }, + "split2@4.2.0": { + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dependencies": {} + }, + "sqlstring@2.3.3": { + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "dependencies": {} + }, + "xtend@4.0.2": { + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dependencies": {} + } + } + } +} diff --git a/test/deno/local.test.ts b/test/deno/local.test.ts index 6f2c1faa1..a119cf3d8 100644 --- a/test/deno/local.test.ts +++ b/test/deno/local.test.ts @@ -1,11 +1,12 @@ import { - DummyDriver, Generated, Kysely, - PostgresAdapter, - PostgresIntrospector, - PostgresQueryCompiler, + PostgresDialect, + MysqlDialect, + sql, } from '../../dist/esm/index.js' +import { createPool } from 'mysql2' +import Pool from 'pg-pool' interface Person { id: Generated @@ -17,29 +18,43 @@ interface Database { person: Person } -const db = new Kysely({ - dialect: { - createAdapter() { - return new PostgresAdapter() - }, - createDriver() { - return new DummyDriver() - }, - createIntrospector(db: Kysely) { - return new PostgresIntrospector(db) - }, - createQueryCompiler() { - return new PostgresQueryCompiler() - }, - }, -}) - -const query = db.selectFrom('person').select('id') -const sql = query.compile() - -if (sql.sql !== 'select "id" from "person"') { - console.error('deno test failed') +const dbs = [ + new Kysely({ + dialect: new PostgresDialect({ + pool: new Pool({ + database: 'kysely_test', + host: 'localhost', + user: 'kysely', + port: 5434, + }), + }), + }), + new Kysely({ + dialect: new MysqlDialect({ + pool: createPool({ + database: 'kysely_test', + host: 'localhost', + user: 'kysely', + password: 'kysely', + port: 3308, + }), + }), + }), +] + +if ( + dbs + .map((db) => db.selectFrom('person').select('id').compile().sql) + .some((sql) => sql.match(/^select ["`]id["`] from ["`]person["`]$/) == null) +) { + console.error('CDN deno test failed') Deno.exit(1) } +const query = sql`select 1` + +await Promise.all(dbs.map((db) => query.execute(db))) + console.error('local deno test passed') + +await Promise.all(dbs.map((db) => db.destroy())) diff --git a/test/node/src/aggregate-function.test.ts b/test/node/src/aggregate-function.test.ts index 5f9088c66..fbd2a04df 100644 --- a/test/node/src/aggregate-function.test.ts +++ b/test/node/src/aggregate-function.test.ts @@ -5,13 +5,13 @@ import { sql, } from '../../../' import { - DIALECTS, Database, destroyTest, initTest, NOT_SUPPORTED, TestContext, testSql, + DIALECTS, } from './test-setup.js' const funcNames = ['avg', 'count', 'max', 'min', 'sum'] as const @@ -44,7 +44,7 @@ for (const dialect of DIALECTS) { (eb) => getAggregateFunctionFromExpressionBuilder( eb, - funcName + funcName, )('person.id').as(`another_${funcName}`), ]) @@ -65,6 +65,14 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select ${funcName}("id") as "${funcName}",`, + `${funcName}("person"."id") as "another_${funcName}"`, + `from "person"`, + ], + parameters: [], + }, sqlite: { sql: [ `select ${funcName}("id") as "${funcName}",`, @@ -86,7 +94,7 @@ for (const dialect of DIALECTS) { (eb) => getAggregateFunctionFromExpressionBuilder( eb, - funcName + funcName, )('person.id') .distinct() .as(`another_${funcName}`), @@ -109,6 +117,14 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select ${funcName}(distinct "id") as "${funcName}",`, + `${funcName}(distinct "person"."id") as "another_${funcName}"`, + `from "person"`, + ], + parameters: [], + }, sqlite: { sql: [ `select ${funcName}(distinct "id") as "${funcName}",`, @@ -130,7 +146,7 @@ for (const dialect of DIALECTS) { (eb) => getAggregateFunctionFromExpressionBuilder( eb, - funcName + funcName, )('person.id') .over() .as(`another_${funcName}`), @@ -153,6 +169,14 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select ${funcName}("id") over() as "${funcName}",`, + `${funcName}("person"."id") over() as "another_${funcName}"`, + `from "person"`, + ], + parameters: [], + }, sqlite: { sql: [ `select ${funcName}("id") over() as "${funcName}",`, @@ -174,7 +198,7 @@ for (const dialect of DIALECTS) { (eb) => getAggregateFunctionFromExpressionBuilder( eb, - funcName + funcName, )('person.id') .over((ob) => ob.partitionBy('person.first_name')) .as(`another_${funcName}`), @@ -201,6 +225,16 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select ${funcName}("id")`, + `over(partition by "first_name") as "${funcName}",`, + `${funcName}("person"."id")`, + `over(partition by "person"."first_name") as "another_${funcName}"`, + `from "person"`, + ], + parameters: [], + }, sqlite: { sql: [ `select ${funcName}("id")`, @@ -220,18 +254,18 @@ for (const dialect of DIALECTS) { const query = ctx.db.selectFrom('person').select([ func('id') .over((ob) => - ob.orderBy('last_name', 'asc').orderBy('first_name', 'asc') + ob.orderBy('last_name', 'asc').orderBy('first_name', 'asc'), ) .as(funcName), (eb) => getAggregateFunctionFromExpressionBuilder( eb, - funcName + funcName, )('person.id') .over((ob) => ob .orderBy('person.last_name', 'desc') - .orderBy('person.first_name', 'desc') + .orderBy('person.first_name', 'desc'), ) .as(`another_${funcName}`), ]) @@ -261,6 +295,18 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select ${funcName}("id")`, + `over(order by "last_name" asc,`, + `"first_name" asc) as "${funcName}",`, + `${funcName}("person"."id")`, + `over(order by "person"."last_name" desc,`, + `"person"."first_name" desc) as "another_${funcName}"`, + `from "person"`, + ], + parameters: [], + }, sqlite: { sql: [ `select ${funcName}("id")`, @@ -285,19 +331,19 @@ for (const dialect of DIALECTS) { ob .partitionBy(['gender']) .orderBy('last_name', 'asc') - .orderBy('first_name', 'asc') + .orderBy('first_name', 'asc'), ) .as(funcName), (eb) => getAggregateFunctionFromExpressionBuilder( eb, - funcName + funcName, )('person.id') .over((ob) => ob .partitionBy('person.gender') .orderBy('person.last_name', 'desc') - .orderBy('person.first_name', 'desc') + .orderBy('person.first_name', 'desc'), ) .as(`another_${funcName}`), ]) @@ -331,6 +377,20 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select ${funcName}("id")`, + `over(partition by "gender"`, + `order by "last_name" asc,`, + `"first_name" asc) as "${funcName}",`, + `${funcName}("person"."id")`, + `over(partition by "person"."gender"`, + `order by "person"."last_name" desc,`, + `"person"."first_name" desc) as "another_${funcName}"`, + `from "person"`, + ], + parameters: [], + }, sqlite: { sql: [ `select ${funcName}("id")`, @@ -353,77 +413,99 @@ for (const dialect of DIALECTS) { it(`should execute a query with ${funcName}(column) in having clause`, async () => { const query = ctx.db .selectFrom('person') - .selectAll() - .groupBy(['person.gender']) - .having(func('person.id'), '>=', 3) + .select(['person.children']) + .groupBy(['person.children']) + .having(func('person.children'), '>=', 3) testSql(query, dialect, { postgres: { sql: [ - `select *`, + `select "person"."children"`, `from "person"`, - `group by "person"."gender"`, - `having ${funcName}("person"."id") >= $1`, + `group by "person"."children"`, + `having ${funcName}("person"."children") >= $1`, ], parameters: [3], }, mysql: { sql: [ - `select *`, + `select \`person\`.\`children\``, `from \`person\``, - `group by \`person\`.\`gender\``, - `having ${funcName}(\`person\`.\`id\`) >= ?`, + `group by \`person\`.\`children\``, + `having ${funcName}(\`person\`.\`children\`) >= ?`, + ], + parameters: [3], + }, + mssql: { + sql: [ + `select "person"."children"`, + `from "person"`, + `group by "person"."children"`, + `having ${funcName}("person"."children") >= @1`, ], parameters: [3], }, sqlite: { sql: [ - `select *`, + `select "person"."children"`, `from "person"`, - `group by "person"."gender"`, - `having ${funcName}("person"."id") >= ?`, + `group by "person"."children"`, + `having ${funcName}("person"."children") >= ?`, ], parameters: [3], }, }) + + await query.execute() }) it(`should execute a query with ${funcName}(column) in order by clause`, async () => { const query = ctx.db .selectFrom('person') - .selectAll() - .groupBy(['person.gender']) - .orderBy(func('person.id'), 'desc') + .select(['person.children']) + .groupBy(['person.children']) + .orderBy(func('person.children'), 'desc') testSql(query, dialect, { postgres: { sql: [ - `select *`, + `select "person"."children"`, `from "person"`, - `group by "person"."gender"`, - `order by ${funcName}("person"."id") desc`, + `group by "person"."children"`, + `order by ${funcName}("person"."children") desc`, ], parameters: [], }, mysql: { sql: [ - `select *`, + `select \`person\`.\`children\``, `from \`person\``, - `group by \`person\`.\`gender\``, - `order by ${funcName}(\`person\`.\`id\`) desc`, + `group by \`person\`.\`children\``, + `order by ${funcName}(\`person\`.\`children\`) desc`, + ], + parameters: [], + }, + mssql: { + sql: [ + `select "person"."children"`, + `from "person"`, + `group by "person"."children"`, + `order by ${funcName}("person"."children") desc`, ], parameters: [], }, sqlite: { sql: [ - `select *`, + `select "person"."children"`, `from "person"`, - `group by "person"."gender"`, - `order by ${funcName}("person"."id") desc`, + `group by "person"."children"`, + `order by ${funcName}("person"."children") desc`, ], parameters: [], }, }) + + await query.execute() }) it(`should execute a query with ${funcName}(column) and a dynamic reference in select clause`, async () => { @@ -436,7 +518,7 @@ for (const dialect of DIALECTS) { (eb) => getAggregateFunctionFromExpressionBuilder( eb, - funcName + funcName, )(dynamicReference).as(`another_${funcName}`), ]) @@ -457,6 +539,14 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select ${funcName}("person"."id") as "${funcName}",`, + `${funcName}("person"."id") as "another_${funcName}"`, + `from "person"`, + ], + parameters: [], + }, sqlite: { sql: [ `select ${funcName}("person"."id") as "${funcName}",`, @@ -466,82 +556,106 @@ for (const dialect of DIALECTS) { parameters: [], }, }) + + await query.execute() }) it(`should execute a query with ${funcName}(column) and a dynamic reference in having clause`, async () => { const query = ctx.db .selectFrom('person') - .selectAll() - .groupBy(['person.gender']) - .having(func(ctx.db.dynamic.ref('person.id')), '>=', 3) + .select(['person.children']) + .groupBy(['person.children']) + .having(func(ctx.db.dynamic.ref('person.children')), '>=', 3) testSql(query, dialect, { postgres: { sql: [ - `select *`, + `select "person"."children"`, `from "person"`, - `group by "person"."gender"`, - `having ${funcName}("person"."id") >= $1`, + `group by "person"."children"`, + `having ${funcName}("person"."children") >= $1`, ], parameters: [3], }, mysql: { sql: [ - `select *`, + `select \`person\`.\`children\``, `from \`person\``, - `group by \`person\`.\`gender\``, - `having ${funcName}(\`person\`.\`id\`) >= ?`, + `group by \`person\`.\`children\``, + `having ${funcName}(\`person\`.\`children\`) >= ?`, + ], + parameters: [3], + }, + mssql: { + sql: [ + `select "person"."children"`, + `from "person"`, + `group by "person"."children"`, + `having ${funcName}("person"."children") >= @1`, ], parameters: [3], }, sqlite: { sql: [ - `select *`, + `select "person"."children"`, `from "person"`, - `group by "person"."gender"`, - `having ${funcName}("person"."id") >= ?`, + `group by "person"."children"`, + `having ${funcName}("person"."children") >= ?`, ], parameters: [3], }, }) + + await query.execute() }) it(`should execute a query with ${funcName}(column) and a dynamic reference in order by clause`, async () => { const query = ctx.db .selectFrom('person') - .selectAll() - .groupBy(['person.gender']) - .orderBy(func(ctx.db.dynamic.ref('person.id')), 'desc') + .select(['person.children']) + .groupBy(['person.children']) + .orderBy(func(ctx.db.dynamic.ref('person.children')), 'desc') testSql(query, dialect, { postgres: { sql: [ - `select *`, + `select "person"."children"`, `from "person"`, - `group by "person"."gender"`, - `order by ${funcName}("person"."id") desc`, + `group by "person"."children"`, + `order by ${funcName}("person"."children") desc`, ], parameters: [], }, mysql: { sql: [ - `select *`, + `select \`person\`.\`children\``, `from \`person\``, - `group by \`person\`.\`gender\``, - `order by ${funcName}(\`person\`.\`id\`) desc`, + `group by \`person\`.\`children\``, + `order by ${funcName}(\`person\`.\`children\`) desc`, + ], + parameters: [], + }, + mssql: { + sql: [ + `select "person"."children"`, + `from "person"`, + `group by "person"."children"`, + `order by ${funcName}("person"."children") desc`, ], parameters: [], }, sqlite: { sql: [ - `select *`, + `select "person"."children"`, `from "person"`, - `group by "person"."gender"`, - `order by ${funcName}("person"."id") desc`, + `group by "person"."children"`, + `order by ${funcName}("person"."children") desc`, ], parameters: [], }, }) + + await query.execute() }) if (dialect === 'postgres' || dialect === 'sqlite') { @@ -555,7 +669,7 @@ for (const dialect of DIALECTS) { (eb) => getAggregateFunctionFromExpressionBuilder( eb, - funcName + funcName, )('person.id') .filterWhere('person.gender', '=', 'female') .as(`another_${funcName}`), @@ -573,6 +687,7 @@ for (const dialect of DIALECTS) { parameters: ['female', 'female'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: [ `select ${funcName}("person"."id")`, @@ -599,7 +714,7 @@ for (const dialect of DIALECTS) { (eb) => getAggregateFunctionFromExpressionBuilder( eb, - funcName + funcName, )('person.id') .filterWhere('person.gender', '=', 'female') .filterWhere('person.middle_name', 'is not', null) @@ -620,6 +735,7 @@ for (const dialect of DIALECTS) { parameters: ['female', 'female'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: [ `select ${funcName}("person"."id")`, @@ -638,45 +754,52 @@ for (const dialect of DIALECTS) { }) it(`should execute a query with ${funcName}(column) filter(where ... or ...) in select clause`, async () => { - const query = ctx.db - .selectFrom('person') - .select([ - func('person.id') - .filterWhere('person.gender', '=', 'female') - .orFilterWhere('person.middle_name', 'is not', null) - .as(funcName), - (eb) => - getAggregateFunctionFromExpressionBuilder( - eb, - funcName - )('person.id') - .filterWhere('person.gender', '=', 'female') - .orFilterWhere('person.middle_name', 'is not', null) - .as(`another_${funcName}`), - ]) + const query = ctx.db.selectFrom('person').select([ + func('person.id') + .filterWhere(({ or, eb }) => + or([ + eb('person.gender', '=', 'female'), + eb('person.middle_name', 'is not', null), + ]), + ) + .as(funcName), + (eb) => + getAggregateFunctionFromExpressionBuilder( + eb, + funcName, + )('person.id') + .filterWhere((eb) => + eb.or([ + eb('person.gender', '=', 'female'), + eb('person.middle_name', 'is not', null), + ]), + ) + .as(`another_${funcName}`), + ]) testSql(query, dialect, { postgres: { sql: [ `select ${funcName}("person"."id")`, - `filter(where "person"."gender" = $1`, - `or "person"."middle_name" is not null) as "${funcName}",`, + `filter(where ("person"."gender" = $1`, + `or "person"."middle_name" is not null)) as "${funcName}",`, `${funcName}("person"."id")`, - `filter(where "person"."gender" = $2`, - `or "person"."middle_name" is not null) as "another_${funcName}"`, + `filter(where ("person"."gender" = $2`, + `or "person"."middle_name" is not null)) as "another_${funcName}"`, `from "person"`, ], parameters: ['female', 'female'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: [ `select ${funcName}("person"."id")`, - `filter(where "person"."gender" = ?`, - `or "person"."middle_name" is not null) as "${funcName}",`, + `filter(where ("person"."gender" = ?`, + `or "person"."middle_name" is not null)) as "${funcName}",`, `${funcName}("person"."id")`, - `filter(where "person"."gender" = ?`, - `or "person"."middle_name" is not null) as "another_${funcName}"`, + `filter(where ("person"."gender" = ?`, + `or "person"."middle_name" is not null)) as "another_${funcName}"`, `from "person"`, ], parameters: ['female', 'female'], @@ -697,7 +820,7 @@ for (const dialect of DIALECTS) { (eb) => getAggregateFunctionFromExpressionBuilder( eb, - funcName + funcName, )('person.id') .filterWhere('person.gender', '=', 'female') .over() @@ -718,6 +841,7 @@ for (const dialect of DIALECTS) { parameters: ['female', 'female'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: [ `select ${funcName}("person"."id")`, @@ -762,6 +886,14 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select ${funcName}(*) as "${funcName}",`, + `${funcName}(*) as "another_${funcName}"`, + 'from "person"', + ], + parameters: [], + }, sqlite: { sql: [ `select ${funcName}(*) as "${funcName}",`, @@ -797,6 +929,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -830,6 +963,14 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select ${funcName}(*) over() as "${funcName}",`, + `${funcName}(*) over() as "another_${funcName}"`, + 'from "person"', + ], + parameters: [], + }, sqlite: { sql: [ `select ${funcName}(*) over() as "${funcName}",`, @@ -869,6 +1010,7 @@ for (const dialect of DIALECTS) { parameters: ['female', 'female'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: [ `select ${funcName}(*)`, @@ -891,25 +1033,35 @@ for (const dialect of DIALECTS) { it('should execute "dynamic" aggregate functions', async () => { const query = ctx.db .selectFrom('person') + .$if(dialect === 'mssql', (qb) => qb.groupBy('person.first_name')) .select([ - ctx.db.fn.agg('rank').over().as('rank'), - (eb) => eb.fn.agg('rank').over().as('another_rank'), + ctx.db.fn + .agg('rank') + .over((ob) => (dialect === 'mssql' ? ob.orderBy('first_name') : ob)) + .as('rank'), + (eb) => + eb.fn + .agg('rank') + .over((ob) => + dialect === 'mssql' ? ob.orderBy('first_name') : ob, + ) + .as('another_rank'), ]) - .$if(dialect === 'postgres', (qb) => + .$if(dialect === 'postgres' || dialect === 'mssql', (qb) => qb.select((eb) => eb.fn .agg('string_agg', ['first_name', sql.lit(',')]) - .distinct() - .as('first_names') - ) + .$call((eb) => (dialect === 'mssql' ? eb : eb.distinct())) + .as('first_names'), + ), ) .$if(dialect === 'mysql' || dialect === 'sqlite', (qb) => qb.select((eb) => eb.fn .agg('group_concat', ['first_name']) .distinct() - .as('first_names') - ) + .as('first_names'), + ), ) testSql(query, dialect, { @@ -931,6 +1083,16 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + 'select rank() over(order by "first_name") as "rank",', + 'rank() over(order by "first_name") as "another_rank",', + `string_agg("first_name", ',') as "first_names"`, + 'from "person"', + 'group by "person"."first_name"', + ], + parameters: [], + }, sqlite: { sql: [ 'select rank() over() as "rank",', @@ -949,14 +1111,14 @@ for (const dialect of DIALECTS) { function getAggregateFunctionFromTestContext( ctx: TestContext, - funcName: typeof funcNames[number] + funcName: (typeof funcNames)[number], ): AggregateFunction { return ctx.db.fn[funcName] as any } function getAggregateFunctionFromExpressionBuilder( eb: ExpressionBuilder, - funcName: typeof funcNames[number] + funcName: (typeof funcNames)[number], ): AggregateFunction { return eb.fn[funcName] as any } @@ -966,5 +1128,5 @@ type AggregateFunction< C extends SimpleReferenceExpression = SimpleReferenceExpression< Database, TB - > + >, > = (column: C) => AggregateFunctionBuilder diff --git a/test/node/src/array.test.ts b/test/node/src/array.test.ts new file mode 100644 index 000000000..d319c795d --- /dev/null +++ b/test/node/src/array.test.ts @@ -0,0 +1,105 @@ +import { Generated, Kysely, sql } from '../../..' + +import { + destroyTest, + initTest, + TestContext, + expect, + Database, + insertDefaultDataSet, + clearDatabase, + Person, + DIALECTS, +} from './test-setup.js' + +interface PersonWithArrays extends Person { + id: Generated + lucky_numbers: number[] + nicknames: string[] | null +} + +if (DIALECTS.includes('postgres')) { + const dialect = 'postgres' + + describe(`${dialect} array tests`, () => { + let ctx: TestContext + let db: Kysely & { person: PersonWithArrays }> + + before(async function () { + ctx = await initTest(this, dialect) + + await ctx.db.schema + .alterTable('person') + .addColumn('lucky_numbers', sql`integer[]`, (col) => + col.notNull().defaultTo(sql`ARRAY[]::integer[]`), + ) + .addColumn('nicknames', sql`text[]`) + .execute() + + db = ctx.db as any + }) + + beforeEach(async () => { + await insertDefaultDataSet(ctx) + + await db + .updateTable('person') + .set({ + nicknames: ['Jenny', 'Jen'], + lucky_numbers: [7, 42], + }) + .where('first_name', '=', 'Jennifer') + .execute() + }) + + afterEach(async () => { + await clearDatabase(ctx) + }) + + after(async () => { + await destroyTest(ctx) + }) + + it('array columns should get returned as arrays by default', async () => { + const jennifer = await db + .selectFrom('person') + .where('first_name', '=', 'Jennifer') + .select(['first_name', 'lucky_numbers', 'nicknames']) + .executeTakeFirstOrThrow() + + expect(jennifer).to.eql({ + first_name: 'Jennifer', + lucky_numbers: [7, 42], + nicknames: ['Jenny', 'Jen'], + }) + }) + + it('should filter using the `any` function', async () => { + const jennifer = await db + .selectFrom('person') + .where((eb) => eb(eb.val(7), '=', eb.fn.any('lucky_numbers'))) + .select(['first_name', 'lucky_numbers', 'nicknames']) + .executeTakeFirstOrThrow() + + expect(jennifer).to.eql({ + first_name: 'Jennifer', + lucky_numbers: [7, 42], + nicknames: ['Jenny', 'Jen'], + }) + }) + + it('should filter using the `any` function on a nullable column', async () => { + const jennifer = await db + .selectFrom('person') + .where((eb) => eb(eb.val('Jen'), '=', eb.fn.any('nicknames'))) + .select(['first_name', 'lucky_numbers', 'nicknames']) + .executeTakeFirstOrThrow() + + expect(jennifer).to.eql({ + first_name: 'Jennifer', + lucky_numbers: [7, 42], + nicknames: ['Jenny', 'Jen'], + }) + }) + }) +} diff --git a/test/node/src/camel-case.test.ts b/test/node/src/camel-case.test.ts index d71ffe4b2..5ba4aeceb 100644 --- a/test/node/src/camel-case.test.ts +++ b/test/node/src/camel-case.test.ts @@ -1,13 +1,14 @@ import { CamelCasePlugin, Generated, Kysely, RawBuilder, sql } from '../../../' import { - DIALECTS, destroyTest, initTest, TestContext, testSql, expect, createTableWithId, + DIALECTS, + NOT_SUPPORTED, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -40,7 +41,10 @@ for (const dialect of DIALECTS) { await createTableWithId(camelDb.schema, dialect, 'camelPerson') .addColumn('firstName', 'varchar(255)') .addColumn('lastName', 'varchar(255)') - .addColumn('preferences', 'json') + .addColumn( + 'preferences', + dialect === 'mssql' ? 'varchar(8000)' : 'json', + ) .execute() }) @@ -74,10 +78,10 @@ for (const dialect of DIALECTS) { // Can't run this test on SQLite because we can't access the same database // from the other Kysely instance. - if (dialect !== 'sqlite') { + if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'mssql') { it('should have created the table and its columns in snake_case', async () => { const result = await sql`select * from camel_person`.execute( - ctx.db + ctx.db, ) expect(result.rows).to.have.length(2) @@ -94,7 +98,7 @@ for (const dialect of DIALECTS) { .innerJoin( 'camelPerson as camelPerson2', 'camelPerson2.id', - 'camelPerson.id' + 'camelPerson.id', ) .orderBy('camelPerson.firstName') @@ -117,6 +121,15 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select "camel_person"."first_name"`, + `from "camel_person"`, + `inner join "camel_person" as "camel_person2" on "camel_person2"."id" = "camel_person"."id"`, + `order by "camel_person"."first_name"`, + ], + parameters: [], + }, sqlite: { sql: [ `select "camel_person"."first_name"`, @@ -144,7 +157,7 @@ for (const dialect of DIALECTS) { .innerJoin( 'camelPerson as camelPerson2', 'camelPerson2.id', - 'camelPerson.id' + 'camelPerson.id', ) .orderBy('camelPerson.firstName') @@ -167,6 +180,15 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select "camel_person"."first_name"`, + `from "camel_person"`, + `inner join "camel_person" as "camel_person2" on "camel_person2"."id" = "camel_person"."id"`, + `order by "camel_person"."first_name"`, + ], + parameters: [], + }, sqlite: { sql: [ `select "camel_person"."first_name"`, @@ -191,7 +213,7 @@ for (const dialect of DIALECTS) { const query = camelDb.schema .alterTable('camelPerson') .addColumn('middleName', 'text', (col) => - col.references('camelPerson.firstName') + col.references('camelPerson.firstName'), ) testSql(query, dialect, { @@ -203,6 +225,10 @@ for (const dialect of DIALECTS) { sql: 'alter table `camel_person` add column `middle_name` text references `camel_person` (`first_name`)', parameters: [], }, + mssql: { + sql: 'alter table "camel_person" add "middle_name" text references "camel_person" ("first_name")', + parameters: [], + }, sqlite: { sql: 'alter table "camel_person" add column "middle_name" text references "camel_person" ("first_name")', parameters: [], @@ -225,6 +251,10 @@ for (const dialect of DIALECTS) { sql: 'delete from `camel_person` as `c` using `camel_person` where `camel_person`.`first_name` = ?', parameters: ['Arnold'], }, + mssql: { + sql: `delete from "camel_person" as "c" using "camel_person" where "camel_person"."first_name" = @1`, + parameters: ['Arnold'], + }, sqlite: { sql: `delete from "camel_person" as "c" using "camel_person" where "camel_person"."first_name" = ?`, parameters: ['Arnold'], @@ -240,7 +270,7 @@ for (const dialect of DIALECTS) { .selectAll() .executeTakeFirstOrThrow() - if (dialect === 'sqlite') { + if (dialect === 'mssql' || dialect === 'sqlite') { data.preferences = JSON.parse(data.preferences.toString()) } @@ -248,6 +278,43 @@ for (const dialect of DIALECTS) { disable_emails: true, }) }) + + if (dialect === 'postgres' || dialect === 'mssql') { + it('should convert merge queries', async () => { + const query = camelDb + .mergeInto('camelPerson') + .using( + 'camelPerson as anotherCamelPerson', + 'camelPerson.firstName', + 'anotherCamelPerson.firstName', + ) + .whenMatched() + .thenUpdateSet((eb) => ({ + firstName: sql`concat(${eb.ref('anotherCamelPerson.firstName')}, ${sql.lit('2')})`, + })) + + testSql(query, dialect, { + postgres: { + sql: [ + `merge into "camel_person"`, + `using "camel_person" as "another_camel_person" on "camel_person"."first_name" = "another_camel_person"."first_name"`, + `when matched then update set "first_name" = concat("another_camel_person"."first_name", '2')`, + ], + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: [ + `merge into "camel_person"`, + `using "camel_person" as "another_camel_person" on "camel_person"."first_name" = "another_camel_person"."first_name"`, + `when matched then update set "first_name" = concat("another_camel_person"."first_name", '2');`, + ], + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + }) + } }) } diff --git a/test/node/src/case.test.ts b/test/node/src/case.test.ts index 1d18ea20e..10de4de85 100644 --- a/test/node/src/case.test.ts +++ b/test/node/src/case.test.ts @@ -33,7 +33,7 @@ for (const dialect of DIALECTS) { const query = ctx.db .selectFrom('person') .select((eb) => - eb.case().when('gender', '=', 'male').then('Mr.').end().as('title') + eb.case().when('gender', '=', 'male').then('Mr.').end().as('title'), ) testSql(query, dialect, { @@ -45,6 +45,10 @@ for (const dialect of DIALECTS) { sql: 'select case when `gender` = ? then ? end as `title` from `person`', parameters: ['male', 'Mr.'], }, + mssql: { + sql: `select case when "gender" = @1 then @2 end as "title" from "person"`, + parameters: ['male', 'Mr.'], + }, sqlite: { sql: `select case when "gender" = ? then ? end as "title" from "person"`, parameters: ['male', 'Mr.'], @@ -58,7 +62,7 @@ for (const dialect of DIALECTS) { const query = ctx.db .selectFrom('person') .select((eb) => - eb.case('gender').when('male').then('Mr.').end().as('title') + eb.case('gender').when('male').then('Mr.').end().as('title'), ) testSql(query, dialect, { @@ -70,6 +74,10 @@ for (const dialect of DIALECTS) { sql: 'select case `gender` when ? then ? end as `title` from `person`', parameters: ['male', 'Mr.'], }, + mssql: { + sql: `select case "gender" when @1 then @2 end as "title" from "person"`, + parameters: ['male', 'Mr.'], + }, sqlite: { sql: `select case "gender" when ? then ? end as "title" from "person"`, parameters: ['male', 'Mr.'], @@ -80,18 +88,16 @@ for (const dialect of DIALECTS) { }) it('should execute a query with a case...when...then...when...then...end operator', async () => { - const query = ctx.db - .selectFrom('person') - .select((eb) => - eb - .case() - .when(eb.cmpr('gender', '=', 'male')) - .then(sql.lit('Mr.')) - .when(eb.cmpr('gender', '=', 'female')) - .then(sql.lit('Mrs.')) - .end() - .as('title') - ) + const query = ctx.db.selectFrom('person').select((eb) => + eb + .case() + .when(eb('gender', '=', 'male')) + .then(sql.lit('Mr.')) + .when(eb('gender', '=', 'female')) + .then(sql.lit('Mrs.')) + .end() + .as('title'), + ) testSql(query, dialect, { postgres: { @@ -110,6 +116,14 @@ for (const dialect of DIALECTS) { ], parameters: ['male', 'female'], }, + mssql: { + sql: [ + `select case when "gender" = @1 then 'Mr.'`, + `when "gender" = @2 then 'Mrs.'`, + `end as "title" from "person"`, + ], + parameters: ['male', 'female'], + }, sqlite: { sql: [ `select case when "gender" = ? then 'Mr.'`, @@ -134,7 +148,7 @@ for (const dialect of DIALECTS) { .when(sql.lit('female')) .then(sql.lit('Mrs.')) .end() - .as('title') + .as('title'), ) testSql(query, dialect, { @@ -154,6 +168,14 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select case "gender" when 'male' then 'Mr.'`, + `when 'female' then 'Mrs.'`, + `end as "title" from "person"`, + ], + parameters: [], + }, sqlite: { sql: [ `select case "gender" when 'male' then 'Mr.'`, @@ -179,7 +201,7 @@ for (const dialect of DIALECTS) { .then('Mrs.') .else(null) .end() - .as('title') + .as('title'), ) testSql(query, dialect, { @@ -187,25 +209,33 @@ for (const dialect of DIALECTS) { sql: [ `select case when "gender" = $1 then $2`, `when "gender" = $3 then $4`, - `else $5 end as "title" from "person"`, + `else null end as "title" from "person"`, ], - parameters: ['male', 'Mr.', 'female', 'Mrs.', null], + parameters: ['male', 'Mr.', 'female', 'Mrs.'], }, mysql: { sql: [ 'select case when `gender` = ? then ?', 'when `gender` = ? then ?', - 'else ? end as `title` from `person`', + 'else null end as `title` from `person`', ], - parameters: ['male', 'Mr.', 'female', 'Mrs.', null], + parameters: ['male', 'Mr.', 'female', 'Mrs.'], + }, + mssql: { + sql: [ + `select case when "gender" = @1 then @2`, + `when "gender" = @3 then @4`, + `else null end as "title" from "person"`, + ], + parameters: ['male', 'Mr.', 'female', 'Mrs.'], }, sqlite: { sql: [ `select case when "gender" = ? then ?`, `when "gender" = ? then ?`, - `else ? end as "title" from "person"`, + `else null end as "title" from "person"`, ], - parameters: ['male', 'Mr.', 'female', 'Mrs.', null], + parameters: ['male', 'Mr.', 'female', 'Mrs.'], }, }) @@ -224,16 +254,16 @@ for (const dialect of DIALECTS) { .case() .when( eb.or([ - eb.cmpr('marital_status', '=', 'single'), - eb.cmpr('marital_status', 'is', null), - ]) + eb('marital_status', '=', 'single'), + eb('marital_status', 'is', null), + ]), ) .then('Ms.') .else('Mrs.') - .end() + .end(), ) .end() - .as('title') + .as('title'), ) testSql(query, dialect, { @@ -259,6 +289,17 @@ for (const dialect of DIALECTS) { ], parameters: ['male', 'Mr.', 'female', 'single', 'Ms.', 'Mrs.'], }, + mssql: { + sql: [ + 'select case "gender" when @1 then @2', + 'when @3 then', + 'case when ("marital_status" = @4 or', + '"marital_status" is null) then @5', + 'else @6 end', + 'end as "title" from "person"', + ], + parameters: ['male', 'Mr.', 'female', 'single', 'Ms.', 'Mrs.'], + }, sqlite: { sql: [ 'select case "gender" when ? then ?', diff --git a/test/node/src/clear.test.ts b/test/node/src/clear.test.ts index 4a8ec9671..dd212189b 100644 --- a/test/node/src/clear.test.ts +++ b/test/node/src/clear.test.ts @@ -1,9 +1,11 @@ import { - DIALECTS, destroyTest, initTest, TestContext, testSql, + NOT_SUPPORTED, + DIALECTS, + limit, } from './test-setup' for (const dialect of DIALECTS) { @@ -34,6 +36,10 @@ for (const dialect of DIALECTS) { sql: 'select `id` from `person`', parameters: [], }, + mssql: { + sql: `select "id" from "person"`, + parameters: [], + }, sqlite: { sql: `select "id" from "person"`, parameters: [], @@ -57,6 +63,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person`', parameters: [], }, + mssql: { + sql: `select * from "person"`, + parameters: [], + }, sqlite: { sql: `select * from "person"`, parameters: [], @@ -78,6 +88,10 @@ for (const dialect of DIALECTS) { sql: 'insert into `person` on conflict do nothing', parameters: [], }, + mssql: { + sql: `insert into "person" on conflict do nothing`, + parameters: [], + }, sqlite: { sql: `insert into "person" on conflict do nothing`, parameters: [], @@ -92,7 +106,7 @@ for (const dialect of DIALECTS) { b .doUpdateSet({ gender: 'other' }) .where('gender', '=', 'male') - .clearWhere() + .clearWhere(), ) testSql(query, dialect, { @@ -104,6 +118,10 @@ for (const dialect of DIALECTS) { sql: 'insert into `person` on conflict do update set `gender` = ?', parameters: ['other'], }, + mssql: { + sql: `insert into "person" on conflict do update set "gender" = @1`, + parameters: ['other'], + }, sqlite: { sql: `insert into "person" on conflict do update set "gender" = ?`, parameters: ['other'], @@ -127,6 +145,10 @@ for (const dialect of DIALECTS) { sql: 'update `person` set `gender` = ?', parameters: ['other'], }, + mssql: { + sql: `update "person" set "gender" = @1`, + parameters: ['other'], + }, sqlite: { sql: `update "person" set "gender" = ?`, parameters: ['other'], @@ -149,6 +171,10 @@ for (const dialect of DIALECTS) { sql: 'delete from `person`', parameters: [], }, + mssql: { + sql: `delete from "person"`, + parameters: [], + }, sqlite: { sql: `delete from "person"`, parameters: [], @@ -156,6 +182,88 @@ for (const dialect of DIALECTS) { }) }) + it('InsertQueryBuilder should clear returning', () => { + const query = ctx.db + .insertInto('person') + .values({ first_name: 'Bruce', last_name: 'Willis', gender: 'male' }) + .returning(['first_name']) + .clearReturning() + + testSql(query, dialect, { + postgres: { + sql: `insert into "person" ("first_name", "last_name", "gender") values ($1, $2, $3)`, + parameters: ['Bruce', 'Willis', 'male'], + }, + mysql: { + sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)', + parameters: ['Bruce', 'Willis', 'male'], + }, + mssql: { + sql: `insert into "person" ("first_name", "last_name", "gender") values (@1, @2, @3)`, + parameters: ['Bruce', 'Willis', 'male'], + }, + sqlite: { + sql: `insert into "person" ("first_name", "last_name", "gender") values (?, ?, ?)`, + parameters: ['Bruce', 'Willis', 'male'], + }, + }) + }) + + it('UpdateQueryBuilder should clear returning', () => { + const query = ctx.db + .updateTable('person') + .set({ marital_status: 'married' }) + .where('first_name', '=', 'Bruce') + .returning(['first_name']) + .clearReturning() + + testSql(query, dialect, { + postgres: { + sql: `update "person" set "marital_status" = $1 where "first_name" = $2`, + parameters: ['married', 'Bruce'], + }, + mysql: { + sql: 'update `person` set `marital_status` = ? where `first_name` = ?', + parameters: ['married', 'Bruce'], + }, + mssql: { + sql: `update "person" set "marital_status" = @1 where "first_name" = @2`, + parameters: ['married', 'Bruce'], + }, + sqlite: { + sql: `update "person" set "marital_status" = ? where "first_name" = ?`, + parameters: ['married', 'Bruce'], + }, + }) + }) + + it('DeleteQueryBuilder should clear returning', () => { + const query = ctx.db + .deleteFrom('person') + .where('first_name', '=', 'James') + .returning(['first_name']) + .clearReturning() + + testSql(query, dialect, { + postgres: { + sql: `delete from "person" where "first_name" = $1`, + parameters: ['James'], + }, + mysql: { + sql: 'delete from `person` where `first_name` = ?', + parameters: ['James'], + }, + mssql: { + sql: `delete from "person" where "first_name" = @1`, + parameters: ['James'], + }, + sqlite: { + sql: `delete from "person" where "first_name" = ?`, + parameters: ['James'], + }, + }) + }) + it('should clear orderBy', () => { const query = ctx.db .selectFrom('person') @@ -172,6 +280,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person`', parameters: [], }, + mssql: { + sql: `select * from "person"`, + parameters: [], + }, sqlite: { sql: `select * from "person"`, parameters: [], @@ -179,34 +291,88 @@ for (const dialect of DIALECTS) { }) }) - it('should clear limit', () => { + it('DeleteQueryBuilder clear orderBy', () => { const query = ctx.db - .selectFrom('person') - .selectAll() - .limit(100) - .clearLimit() + .deleteFrom('person') + .where('gender', '=', 'male') + .orderBy('id') + .clearOrderBy() testSql(query, dialect, { postgres: { - sql: `select * from "person"`, - parameters: [], + sql: `delete from "person" where "gender" = $1`, + parameters: ['male'], }, mysql: { - sql: 'select * from `person`', - parameters: [], + sql: 'delete from `person` where `gender` = ?', + parameters: ['male'], + }, + mssql: { + sql: `delete from "person" where "gender" = @1`, + parameters: ['male'], }, sqlite: { - sql: `select * from "person"`, - parameters: [], + sql: `delete from "person" where "gender" = ?`, + parameters: ['male'], }, }) }) + if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'sqlite') { + it('should clear limit', () => { + const query = ctx.db + .selectFrom('person') + .selectAll() + .limit(100) + .clearLimit() + + testSql(query, dialect, { + postgres: { + sql: `select * from "person"`, + parameters: [], + }, + mysql: { + sql: 'select * from `person`', + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: `select * from "person"`, + parameters: [], + }, + }) + }) + + it('DeleteQueryBuilder should clear limit', () => { + const query = ctx.db + .deleteFrom('person') + .where('gender', '=', 'male') + .limit(1) + .clearLimit() + + testSql(query, dialect, { + postgres: { + sql: `delete from "person" where "gender" = $1`, + parameters: ['male'], + }, + mysql: { + sql: 'delete from `person` where `gender` = ?', + parameters: ['male'], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: `delete from "person" where "gender" = ?`, + parameters: ['male'], + }, + }) + }) + } + it('should clear offset', () => { const query = ctx.db .selectFrom('person') .selectAll() - .limit(1) + .$call(limit(1, dialect)) .offset(100) .clearOffset() @@ -219,11 +385,42 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` limit ?', parameters: [1], }, + mssql: { + sql: `select top(1) * from "person"`, + parameters: [], + }, sqlite: { sql: `select * from "person" limit ?`, parameters: [1], }, }) }) + + it('should clear groupBy', () => { + const query = ctx.db + .selectFrom('person') + .selectAll() + .groupBy('id') + .clearGroupBy() + + testSql(query, dialect, { + postgres: { + sql: `select * from "person"`, + parameters: [], + }, + mysql: { + sql: 'select * from `person`', + parameters: [], + }, + mssql: { + sql: `select * from "person"`, + parameters: [], + }, + sqlite: { + sql: `select * from "person"`, + parameters: [], + }, + }) + }) }) } diff --git a/test/node/src/coalesce.test.ts b/test/node/src/coalesce.test.ts index fc7cf02f2..133d9e730 100644 --- a/test/node/src/coalesce.test.ts +++ b/test/node/src/coalesce.test.ts @@ -1,6 +1,5 @@ import { sql } from '../../..' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -8,6 +7,7 @@ import { NOT_SUPPORTED, TestContext, testSql, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -69,6 +69,7 @@ for (const dialect of DIALECTS) { ], parameters: [1], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -84,37 +85,51 @@ for (const dialect of DIALECTS) { .select([ coalesce('first_name', 'last_name').as('ColumnReference0'), coalesce('first_name', ctx.db.dynamic.ref('last_name')).as( - 'ColumnReference1' + 'ColumnReference1', ), - coalesce('first_name', sql`${1}`).as('ColumnReference2'), + ...(dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'sqlite' + ? [coalesce('first_name', sql`${1}`).as('ColumnReference2')] + : []), coalesce('first_name', max('last_name')).as('ColumnReference3'), coalesce( ctx.db.dynamic.ref('first_name'), - ctx.db.dynamic.ref('last_name') + ctx.db.dynamic.ref('last_name'), ).as('DynamicReference0'), coalesce(ctx.db.dynamic.ref('first_name'), 'last_name').as( - 'DynamicReference1' - ), - coalesce(ctx.db.dynamic.ref('first_name'), sql`${2}`).as( - 'DynamicReference2' + 'DynamicReference1', ), + ...(dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'sqlite' + ? [ + coalesce(ctx.db.dynamic.ref('first_name'), sql`${2}`).as( + 'DynamicReference2', + ), + ] + : []), coalesce(ctx.db.dynamic.ref('first_name'), max('last_name')).as( - 'DynamicReference3' + 'DynamicReference3', ), coalesce(sql`${3}`, sql`${4}`).as('RawBuilder0'), coalesce(sql`${5}`, 'last_name').as('RawBuilder1'), coalesce(sql`${6}`, ctx.db.dynamic.ref('last_name')).as( - 'RawBuilder2' + 'RawBuilder2', ), coalesce(sql`${7}`, max('last_name')).as('RawBuilder3'), coalesce(max('first_name'), max('last_name')).as( - 'AggregateFunction0' + 'AggregateFunction0', ), coalesce(max('first_name'), 'last_name').as('AggregateFunction1'), coalesce(max('first_name'), ctx.db.dynamic.ref('last_name')).as( - 'AggregateFunction2' + 'AggregateFunction2', ), - coalesce(max('first_name'), sql`${8}`).as('AggregateFunction3'), + ...(dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'sqlite' + ? [coalesce(max('first_name'), sql`${8}`).as('AggregateFunction3')] + : []), ]) .groupBy(['first_name', 'last_name']) @@ -167,6 +182,27 @@ for (const dialect of DIALECTS) { ], parameters: [1, 2, 3, 4, 5, 6, 7, 8], }, + mssql: { + sql: [ + 'select', + 'coalesce("first_name", "last_name") as "ColumnReference0",', + 'coalesce("first_name", "last_name") as "ColumnReference1",', + 'coalesce("first_name", max("last_name")) as "ColumnReference3",', + 'coalesce("first_name", "last_name") as "DynamicReference0",', + 'coalesce("first_name", "last_name") as "DynamicReference1",', + 'coalesce("first_name", max("last_name")) as "DynamicReference3",', + 'coalesce(@1, @2) as "RawBuilder0",', + 'coalesce(@3, "last_name") as "RawBuilder1",', + 'coalesce(@4, "last_name") as "RawBuilder2",', + 'coalesce(@5, max("last_name")) as "RawBuilder3",', + 'coalesce(max("first_name"), max("last_name")) as "AggregateFunction0",', + 'coalesce(max("first_name"), "last_name") as "AggregateFunction1",', + 'coalesce(max("first_name"), "last_name") as "AggregateFunction2"', + 'from "person"', + 'group by "first_name", "last_name"', + ], + parameters: [3, 4, 5, 6, 7], + }, sqlite: { sql: [ 'select', @@ -205,7 +241,7 @@ for (const dialect of DIALECTS) { 'first_name', ctx.db.dynamic.ref('last_name'), ctx.db.fn.max('last_name'), - sql.lit('(N/A)') + sql.lit('(N/A)'), ) .as('name'), ]) @@ -230,6 +266,15 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + 'select', + `coalesce("first_name", "last_name", max("last_name"), '(N/A)') as "name"`, + 'from "person"', + 'group by "first_name", "last_name"', + ], + parameters: [], + }, sqlite: { sql: [ 'select', diff --git a/test/node/src/deduplicate-joins.test.ts b/test/node/src/deduplicate-joins.test.ts index 917631690..1404a59c0 100644 --- a/test/node/src/deduplicate-joins.test.ts +++ b/test/node/src/deduplicate-joins.test.ts @@ -1,13 +1,13 @@ import { DeduplicateJoinsPlugin } from '../../..' import { - DIALECTS, clearDatabase, destroyTest, initTest, TestContext, testSql, insertDefaultDataSet, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -46,6 +46,10 @@ for (const dialect of DIALECTS) { sql: 'select from `person` inner join `pet` on `pet`.`owner_id` = `person`.`id`', parameters: [], }, + mssql: { + sql: 'select from "person" inner join "pet" on "pet"."owner_id" = "person"."id"', + parameters: [], + }, sqlite: { sql: 'select from "person" inner join "pet" on "pet"."owner_id" = "person"."id"', parameters: [], @@ -65,7 +69,7 @@ for (const dialect of DIALECTS) { (join) => join .onRef('p.owner_id', '=', 'person.id') - .on('p.species', 'in', ['cat', 'hamster']) + .on('p.species', 'in', ['cat', 'hamster']), ) .innerJoin( ctx.db @@ -75,7 +79,7 @@ for (const dialect of DIALECTS) { (join) => join .onRef('p.owner_id', '=', 'person.id') - .on('p.species', 'in', ['cat', 'hamster']) + .on('p.species', 'in', ['cat', 'hamster']), ) testSql(query, dialect, { @@ -87,6 +91,10 @@ for (const dialect of DIALECTS) { sql: 'select from `person` inner join (select `owner_id`, `id` as `pet_id`, `species` from `pet`) as `p` on `p`.`owner_id` = `person`.`id` and `p`.`species` in (?, ?)', parameters: ['cat', 'hamster'], }, + mssql: { + sql: 'select from "person" inner join (select "owner_id", "id" as "pet_id", "species" from "pet") as "p" on "p"."owner_id" = "person"."id" and "p"."species" in (@1, @2)', + parameters: ['cat', 'hamster'], + }, sqlite: { sql: 'select from "person" inner join (select "owner_id", "id" as "pet_id", "species" from "pet") as "p" on "p"."owner_id" = "person"."id" and "p"."species" in (?, ?)', parameters: ['cat', 'hamster'], @@ -110,6 +118,10 @@ for (const dialect of DIALECTS) { sql: 'select from `person` inner join `pet` on `pet`.`owner_id` = `person`.`id` inner join `toy` on `toy`.`pet_id` = `pet`.`id`', parameters: [], }, + mssql: { + sql: 'select from "person" inner join "pet" on "pet"."owner_id" = "person"."id" inner join "toy" on "toy"."pet_id" = "pet"."id"', + parameters: [], + }, sqlite: { sql: 'select from "person" inner join "pet" on "pet"."owner_id" = "person"."id" inner join "toy" on "toy"."pet_id" = "pet"."id"', parameters: [], diff --git a/test/node/src/delete.test.ts b/test/node/src/delete.test.ts index 4412b51d1..efa0c61d4 100644 --- a/test/node/src/delete.test.ts +++ b/test/node/src/delete.test.ts @@ -1,7 +1,6 @@ import { DeleteResult, sql } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -11,6 +10,8 @@ import { NOT_SUPPORTED, insertDefaultDataSet, DEFAULT_DATA_SET, + DIALECTS, + Species, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -45,6 +46,10 @@ for (const dialect of DIALECTS) { sql: 'delete from `person` where `gender` = ?', parameters: ['female'], }, + mssql: { + sql: 'delete from "person" where "gender" = @1', + parameters: ['female'], + }, sqlite: { sql: 'delete from "person" where "gender" = ?', parameters: ['female'], @@ -62,7 +67,7 @@ for (const dialect of DIALECTS) { .select(['first_name', 'last_name', 'gender']) .orderBy('first_name') .orderBy('last_name') - .execute() + .execute(), ).to.eql([ { first_name: 'Arnold', last_name: 'Schwarzenegger', gender: 'male' }, { first_name: 'Sylvester', last_name: 'Stallone', gender: 'male' }, @@ -72,8 +77,31 @@ for (const dialect of DIALECTS) { it('should delete two rows', async () => { const query = ctx.db .deleteFrom('person') - .where('first_name', '=', 'Jennifer') - .orWhere('first_name', '=', 'Arnold') + .where((eb) => + eb.or([ + eb('first_name', '=', 'Jennifer'), + eb('first_name', '=', 'Arnold'), + ]), + ) + + testSql(query, dialect, { + postgres: { + sql: 'delete from "person" where ("first_name" = $1 or "first_name" = $2)', + parameters: ['Jennifer', 'Arnold'], + }, + mysql: { + sql: 'delete from `person` where (`first_name` = ? or `first_name` = ?)', + parameters: ['Jennifer', 'Arnold'], + }, + mssql: { + sql: 'delete from "person" where ("first_name" = @1 or "first_name" = @2)', + parameters: ['Jennifer', 'Arnold'], + }, + sqlite: { + sql: 'delete from "person" where ("first_name" = ? or "first_name" = ?)', + parameters: ['Jennifer', 'Arnold'], + }, + }) const result = await query.executeTakeFirst() @@ -86,6 +114,25 @@ for (const dialect of DIALECTS) { .deleteFrom('person') .where('first_name', '=', 'Nobody') + testSql(query, dialect, { + postgres: { + sql: 'delete from "person" where "first_name" = $1', + parameters: ['Nobody'], + }, + mysql: { + sql: 'delete from `person` where `first_name` = ?', + parameters: ['Nobody'], + }, + mssql: { + sql: 'delete from "person" where "first_name" = @1', + parameters: ['Nobody'], + }, + sqlite: { + sql: 'delete from "person" where "first_name" = ?', + parameters: ['Nobody'], + }, + }) + const result = await query.executeTakeFirst() expect(result).to.be.instanceOf(DeleteResult) @@ -102,6 +149,7 @@ for (const dialect of DIALECTS) { parameters: [2], }, postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -125,6 +173,7 @@ for (const dialect of DIALECTS) { parameters: ['male'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: 'delete from "person" where "gender" = ? returning "first_name", "last_name" as "last"', parameters: ['male'], @@ -156,6 +205,7 @@ for (const dialect of DIALECTS) { parameters: ['female'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: 'delete from "person" where "gender" = ? returning "first_name", "last_name"', parameters: ['female'], @@ -173,7 +223,7 @@ for (const dialect of DIALECTS) { .deleteFrom('person') .using('pet') .whereRef('pet.owner_id', '=', 'person.id') - .where('pet.species', '=', sql`${'NO_SUCH_SPECIES'}`) + .where('pet.species', '=', sql`${'NO_SUCH_SPECIES'}`) testSql(query, dialect, { postgres: { @@ -186,6 +236,7 @@ for (const dialect of DIALECTS) { parameters: ['NO_SUCH_SPECIES'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -212,6 +263,7 @@ for (const dialect of DIALECTS) { parameters: [0], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -240,6 +292,7 @@ for (const dialect of DIALECTS) { parameters: ['Bob'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -262,6 +315,7 @@ for (const dialect of DIALECTS) { parameters: ['cat'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -290,6 +344,7 @@ for (const dialect of DIALECTS) { parameters: ['Zoro'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -318,6 +373,7 @@ for (const dialect of DIALECTS) { parameters: ['Luffy'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -346,6 +402,7 @@ for (const dialect of DIALECTS) { parameters: ['Itachi'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -368,6 +425,7 @@ for (const dialect of DIALECTS) { parameters: ['male'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -386,6 +444,7 @@ for (const dialect of DIALECTS) { parameters: ['male'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -414,6 +473,7 @@ for (const dialect of DIALECTS) { parameters: ['Bob'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -427,7 +487,7 @@ for (const dialect of DIALECTS) { .deleteFrom('person') .using('person') .innerJoin('pet', 'pet.owner_id', 'person.id') - .where('pet.species', '=', sql`${'NO_SUCH_SPECIES'}`) + .where('pet.species', '=', sql`${'NO_SUCH_SPECIES'}`) testSql(query, dialect, { postgres: NOT_SUPPORTED, @@ -440,6 +500,7 @@ for (const dialect of DIALECTS) { ], parameters: ['NO_SUCH_SPECIES'], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -451,7 +512,7 @@ for (const dialect of DIALECTS) { .deleteFrom('person') .using('person') .leftJoin('pet', 'pet.owner_id', 'person.id') - .where('pet.species', '=', sql`${'NO_SUCH_SPECIES'}`) + .where('pet.species', '=', sql`${'NO_SUCH_SPECIES'}`) testSql(query, dialect, { postgres: NOT_SUPPORTED, @@ -464,6 +525,7 @@ for (const dialect of DIALECTS) { ], parameters: ['NO_SUCH_SPECIES'], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -476,22 +538,20 @@ for (const dialect of DIALECTS) { .using('person') .innerJoin('pet', 'pet.owner_id', 'person.id') .leftJoin('toy', 'toy.pet_id', 'pet.id') - .where('pet.species', '=', sql`${'NO_SUCH_SPECIES'}`) - .orWhere('toy.price', '=', 0) + .where(({ eb, or }) => + or([ + eb('pet.species', '=', sql`${'NO_SUCH_SPECIES'}`), + eb('toy.price', '=', 0), + ]), + ) testSql(query, dialect, { postgres: NOT_SUPPORTED, mysql: { - sql: [ - 'delete from `person`', - 'using `person`', - 'inner join `pet` on `pet`.`owner_id` = `person`.`id`', - 'left join `toy` on `toy`.`pet_id` = `pet`.`id`', - 'where `pet`.`species` = ?', - 'or `toy`.`price` = ?', - ], + sql: 'delete from `person` using `person` inner join `pet` on `pet`.`owner_id` = `person`.`id` left join `toy` on `toy`.`pet_id` = `pet`.`id` where (`pet`.`species` = ? or `toy`.`price` = ?)', parameters: ['NO_SUCH_SPECIES', 0], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -502,7 +562,7 @@ for (const dialect of DIALECTS) { const query = ctx.db .deleteFrom('person') .using(['person', 'pet']) - .where('pet.species', '=', sql`${'NO_SUCH_SPECIES'}`) + .where('pet.species', '=', sql`${'NO_SUCH_SPECIES'}`) testSql(query, dialect, { postgres: NOT_SUPPORTED, @@ -514,6 +574,7 @@ for (const dialect of DIALECTS) { ], parameters: ['NO_SUCH_SPECIES'], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -538,6 +599,7 @@ for (const dialect of DIALECTS) { ], parameters: [0], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -562,6 +624,7 @@ for (const dialect of DIALECTS) { ], parameters: [0], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -586,6 +649,7 @@ for (const dialect of DIALECTS) { ], parameters: [911], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -610,6 +674,7 @@ for (const dialect of DIALECTS) { ], parameters: [911], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -636,6 +701,7 @@ for (const dialect of DIALECTS) { ], parameters: [1000], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -662,6 +728,7 @@ for (const dialect of DIALECTS) { ], parameters: [1000], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -688,6 +755,7 @@ for (const dialect of DIALECTS) { ], parameters: [1000], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -714,6 +782,7 @@ for (const dialect of DIALECTS) { ], parameters: [1000], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -740,6 +809,7 @@ for (const dialect of DIALECTS) { ], parameters: [1000], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -766,6 +836,7 @@ for (const dialect of DIALECTS) { ], parameters: [1000], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -792,9 +863,105 @@ for (const dialect of DIALECTS) { first_name, last_name, gender, - })) + })), ) }) } + + if (dialect === 'mssql') { + it('should delete top', async () => { + const query = ctx.db + .deleteFrom('person') + .top(1) + .where('gender', '=', 'male') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'delete top(1) from "person" where "gender" = @1', + parameters: ['male'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirst() + + expect(result).to.be.instanceOf(DeleteResult) + expect(result.numDeletedRows).to.equal(1n) + }) + + it('should delete top percent', async () => { + const query = ctx.db + .deleteFrom('person') + .top(50, 'percent') + .where('gender', '=', 'male') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'delete top(50) percent from "person" where "gender" = @1', + parameters: ['male'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirst() + + expect(result).to.be.instanceOf(DeleteResult) + }) + } + + if (dialect === 'mssql') { + it('should return deleted rows when `output` is used', async () => { + const query = ctx.db + .deleteFrom('person') + .output(['deleted.first_name', 'deleted.last_name as last']) + .where('gender', '=', 'male') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'delete from "person" output "deleted"."first_name", "deleted"."last_name" as "last" where "gender" = @1', + parameters: ['male'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.execute() + + expect(result).to.have.length(2) + expect(Object.keys(result[0]).sort()).to.eql(['first_name', 'last']) + expect(result).to.containSubset([ + { first_name: 'Arnold', last: 'Schwarzenegger' }, + { first_name: 'Sylvester', last: 'Stallone' }, + ]) + }) + + it('conditional `output` statement should add optional fields', async () => { + const condition = true + + const query = ctx.db + .deleteFrom('person') + .output('deleted.first_name') + .$if(condition, (qb) => qb.output('deleted.last_name')) + .where('gender', '=', 'female') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'delete from "person" output "deleted"."first_name", "deleted"."last_name" where "gender" = @1', + parameters: ['female'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + expect(result.last_name).to.equal('Aniston') + }) + } }) } diff --git a/test/node/src/error-stack.test.ts b/test/node/src/error-stack.test.ts index a5929ee9d..84cde4902 100644 --- a/test/node/src/error-stack.test.ts +++ b/test/node/src/error-stack.test.ts @@ -2,11 +2,11 @@ import { AssertionError } from 'chai' import { sql } from '../../../' import { - DIALECTS, destroyTest, initTest, TestContext, expect, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -38,7 +38,7 @@ for (const dialect of DIALECTS) { try { await query.execute() expect.fail( - `query "${query.compile().sql}" was supposed to throw but didn't` + `query "${query.compile().sql}" was supposed to throw but didn't`, ) } catch (err: any) { if (err instanceof AssertionError) { diff --git a/test/node/src/execute.test.ts b/test/node/src/execute.test.ts index 470aa7b80..8fb97c1bf 100644 --- a/test/node/src/execute.test.ts +++ b/test/node/src/execute.test.ts @@ -6,13 +6,13 @@ import { QueryNode, } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, insertPersons, TestContext, expect, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -128,7 +128,7 @@ for (const dialect of DIALECTS) { beforeEach(() => { executorSpy = sandbox.spy( ctx.db.getExecutor() as QueryExecutor, - 'executeQuery' + 'executeQuery', ) }) diff --git a/test/node/src/explain.test.ts b/test/node/src/explain.test.ts index a37b02362..441cfcd1a 100644 --- a/test/node/src/explain.test.ts +++ b/test/node/src/explain.test.ts @@ -2,16 +2,16 @@ import { expect } from 'chai' import { createSandbox, SinonSpy } from 'sinon' import { DefaultQueryExecutor, sql } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, insertDefaultDataSet, NOT_SUPPORTED, TestContext, + DIALECTS, } from './test-setup.js' -for (const dialect of DIALECTS) { +for (const dialect of DIALECTS.filter((dialect) => dialect !== 'mssql')) { describe(`${dialect}: explain test`, () => { let ctx: TestContext const sandbox = createSandbox() @@ -25,7 +25,7 @@ for (const dialect of DIALECTS) { await insertDefaultDataSet(ctx) executeQuerySpy = sandbox.spy( DefaultQueryExecutor.prototype, - 'executeQuery' + 'executeQuery', ) }) @@ -46,8 +46,9 @@ for (const dialect of DIALECTS) { { postgres: 'explain select * from "person" limit $1', mysql: 'explain select * from `person` limit ?', + mssql: NOT_SUPPORTED, sqlite: 'explain select * from "person" limit ?', - }[dialect] + }[dialect], ) }) @@ -59,8 +60,9 @@ for (const dialect of DIALECTS) { { postgres: 'explain insert into "person" ("gender") values ($1)', mysql: 'explain insert into `person` (`gender`) values (?)', + mssql: NOT_SUPPORTED, sqlite: 'explain insert into "person" ("gender") values (?)', - }[dialect] + }[dialect], ) }) @@ -76,8 +78,9 @@ for (const dialect of DIALECTS) { { postgres: 'explain update "person" set "gender" = $1 where "id" = $2', mysql: 'explain update `person` set `gender` = ? where `id` = ?', + mssql: NOT_SUPPORTED, sqlite: 'explain update "person" set "gender" = ? where "id" = ?', - }[dialect] + }[dialect], ) }) @@ -89,8 +92,9 @@ for (const dialect of DIALECTS) { { postgres: 'explain delete from "person" where "id" = $1', mysql: 'explain delete from `person` where `id` = ?', + mssql: NOT_SUPPORTED, sqlite: 'explain delete from "person" where "id" = ?', - }[dialect] + }[dialect], ) }) @@ -103,7 +107,7 @@ for (const dialect of DIALECTS) { expect(executeQuerySpy.calledOnce).to.be.true expect(executeQuerySpy.getCall(0).args[0].sql).to.equal( - 'explain replace into `person` (`id`, `gender`) values (?, ?)' + 'explain replace into `person` (`id`, `gender`) values (?, ?)', ) }) } @@ -122,8 +126,9 @@ for (const dialect of DIALECTS) { postgres: 'explain (analyze, format json) select * from "person" where "id" = $1', mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, - }[dialect] + }[dialect], ) }) } @@ -142,8 +147,9 @@ for (const dialect of DIALECTS) { postgres: NOT_SUPPORTED, mysql: 'explain analyze format=tree select * from `person` where `id` = ?', + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, - }[dialect] + }[dialect], ) }) } diff --git a/test/node/src/expression.test.ts b/test/node/src/expression.test.ts index 691833500..fc9bd13fb 100644 --- a/test/node/src/expression.test.ts +++ b/test/node/src/expression.test.ts @@ -1,11 +1,11 @@ import { - DIALECTS, clearDatabase, destroyTest, initTest, insertDefaultDataSet, TestContext, testSql, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -33,38 +33,169 @@ for (const dialect of DIALECTS) { .selectFrom('person') .selectAll('person') .where( - ({ and, or, cmpr, bxp, fn, exists, not, ref, val, selectFrom }) => + ({ and, or, eb, fn, exists, not, ref, val, selectFrom, parens }) => and([ or([ - not(cmpr('first_name', '=', 'Jennifer')), - cmpr(bxp('id', '+', 1), '>', 10), - cmpr(ref('id'), 'in', val([10, 20, 30])), - or([cmpr(fn('upper', ['first_name']), '=', 'SYLVESTER')]), + not(eb('first_name', '=', 'Jennifer')), + eb(eb('id', '+', 1), '>', 10), + eb(ref('id'), 'in', [10, 20, 30].map(val)), + or([eb(fn('upper', ['first_name']), '=', 'SYLVESTER')]), // Empty or or([]), ]), exists( selectFrom('pet') .select('pet.id') - .whereRef('pet.owner_id', '=', 'person.id') + .whereRef('pet.owner_id', '=', 'person.id'), ), // Empty and and([]), - ]) + eb('id', '=', 1) + .or('id', '=', 2) + .or('id', '=', 3) + .or(eb('id', '=', 4)), + eb('id', '=', 1) + .and('first_name', '=', 'Jennifer') + .and('last_name', '=', 'Aniston') + .and(eb('marital_status', '=', 'divorced')), + // Should not produce double parens + parens(eb('id', '=', 1).or('id', '=', 2)), + eb(parens('id', '+', 1), '>', 10), + // Object and + eb.and({ first_name: 'Jennifer', last_name: 'Aniston' }), + // Object or + eb.or({ + first_name: eb.ref('last_name'), + last_name: eb.ref('first_name'), + }), + // Boolean literal + ...(dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'sqlite' + ? [eb.lit(true)] + : []), + // Between expressions + eb.between('id', 1000, 2000), + ...(dialect === 'postgres' + ? [eb.betweenSymmetric('id', 3000, 4000)] + : []), + ]), ) testSql(query, dialect, { postgres: { - sql: 'select "person".* from "person" where ((not "first_name" = $1 or "id" + $2 > $3 or "id" in ($4, $5, $6) or upper("first_name") = $7 or false) and exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id") and true)', - parameters: ['Jennifer', 1, 10, 10, 20, 30, 'SYLVESTER'], + sql: 'select "person".* from "person" where ((not "first_name" = $1 or "id" + $2 > $3 or "id" in ($4, $5, $6) or upper("first_name") = $7 or 1 = 0) and exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id") and 1 = 1 and ("id" = $8 or "id" = $9 or "id" = $10 or "id" = $11) and ("id" = $12 and "first_name" = $13 and "last_name" = $14 and "marital_status" = $15) and ("id" = $16 or "id" = $17) and ("id" + $18) > $19 and ("first_name" = $20 and "last_name" = $21) and ("first_name" = "last_name" or "last_name" = "first_name") and true and "id" between $22 and $23 and "id" between symmetric $24 and $25)', + parameters: [ + 'Jennifer', + 1, + 10, + 10, + 20, + 30, + 'SYLVESTER', + 1, + 2, + 3, + 4, + 1, + 'Jennifer', + 'Aniston', + 'divorced', + 1, + 2, + 1, + 10, + 'Jennifer', + 'Aniston', + 1000, + 2000, + 3000, + 4000, + ], }, mysql: { - sql: 'select `person`.* from `person` where ((not `first_name` = ? or `id` + ? > ? or `id` in (?, ?, ?) or upper(`first_name`) = ? or false) and exists (select `pet`.`id` from `pet` where `pet`.`owner_id` = `person`.`id`) and true)', - parameters: ['Jennifer', 1, 10, 10, 20, 30, 'SYLVESTER'], + sql: 'select `person`.* from `person` where ((not `first_name` = ? or `id` + ? > ? or `id` in (?, ?, ?) or upper(`first_name`) = ? or 1 = 0) and exists (select `pet`.`id` from `pet` where `pet`.`owner_id` = `person`.`id`) and 1 = 1 and (`id` = ? or `id` = ? or `id` = ? or `id` = ?) and (`id` = ? and `first_name` = ? and `last_name` = ? and `marital_status` = ?) and (`id` = ? or `id` = ?) and (`id` + ?) > ? and (`first_name` = ? and `last_name` = ?) and (`first_name` = `last_name` or `last_name` = `first_name`) and true and `id` between ? and ?)', + parameters: [ + 'Jennifer', + 1, + 10, + 10, + 20, + 30, + 'SYLVESTER', + 1, + 2, + 3, + 4, + 1, + 'Jennifer', + 'Aniston', + 'divorced', + 1, + 2, + 1, + 10, + 'Jennifer', + 'Aniston', + 1000, + 2000, + ], + }, + mssql: { + sql: 'select "person".* from "person" where ((not "first_name" = @1 or "id" + @2 > @3 or "id" in (@4, @5, @6) or upper("first_name") = @7 or 1 = 0) and exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id") and 1 = 1 and ("id" = @8 or "id" = @9 or "id" = @10 or "id" = @11) and ("id" = @12 and "first_name" = @13 and "last_name" = @14 and "marital_status" = @15) and ("id" = @16 or "id" = @17) and ("id" + @18) > @19 and ("first_name" = @20 and "last_name" = @21) and ("first_name" = "last_name" or "last_name" = "first_name") and "id" between @22 and @23)', + parameters: [ + 'Jennifer', + 1, + 10, + 10, + 20, + 30, + 'SYLVESTER', + 1, + 2, + 3, + 4, + 1, + 'Jennifer', + 'Aniston', + 'divorced', + 1, + 2, + 1, + 10, + 'Jennifer', + 'Aniston', + 1000, + 2000, + ], }, sqlite: { - sql: 'select "person".* from "person" where ((not "first_name" = ? or "id" + ? > ? or "id" in (?, ?, ?) or upper("first_name") = ? or false) and exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id") and true)', - parameters: ['Jennifer', 1, 10, 10, 20, 30, 'SYLVESTER'], + sql: 'select "person".* from "person" where ((not "first_name" = ? or "id" + ? > ? or "id" in (?, ?, ?) or upper("first_name") = ? or 1 = 0) and exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id") and 1 = 1 and ("id" = ? or "id" = ? or "id" = ? or "id" = ?) and ("id" = ? and "first_name" = ? and "last_name" = ? and "marital_status" = ?) and ("id" = ? or "id" = ?) and ("id" + ?) > ? and ("first_name" = ? and "last_name" = ?) and ("first_name" = "last_name" or "last_name" = "first_name") and true and "id" between ? and ?)', + parameters: [ + 'Jennifer', + 1, + 10, + 10, + 20, + 30, + 'SYLVESTER', + 1, + 2, + 3, + 4, + 1, + 'Jennifer', + 'Aniston', + 'divorced', + 1, + 2, + 1, + 10, + 'Jennifer', + 'Aniston', + 1000, + 2000, + ], }, }) diff --git a/test/node/src/group-by.test.ts b/test/node/src/group-by.test.ts index 13f349be8..af5e3c198 100644 --- a/test/node/src/group-by.test.ts +++ b/test/node/src/group-by.test.ts @@ -1,7 +1,6 @@ import { sql } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -9,6 +8,8 @@ import { testSql, expect, insertDefaultDataSet, + NOT_SUPPORTED, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -47,6 +48,10 @@ for (const dialect of DIALECTS) { sql: 'select `gender`, max(first_name) as `max_first_name` from `person` group by `gender` order by `gender`', parameters: [], }, + mssql: { + sql: 'select "gender", max(first_name) as "max_first_name" from "person" group by "gender" order by "gender"', + parameters: [], + }, sqlite: { sql: 'select "gender", max(first_name) as "max_first_name" from "person" group by "gender" order by "gender"', parameters: [], @@ -68,42 +73,45 @@ for (const dialect of DIALECTS) { ]) }) - it('group by selection', async () => { - const query = ctx.db - .selectFrom('person') - .select(['gender as g', sql`max(first_name)`.as('max_first_name')]) - .groupBy('g') - .orderBy('g') + if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'sqlite') { + it('group by selection', async () => { + const query = ctx.db + .selectFrom('person') + .select(['gender as g', sql`max(first_name)`.as('max_first_name')]) + .groupBy('g') + .orderBy('g') - testSql(query, dialect, { - postgres: { - sql: 'select "gender" as "g", max(first_name) as "max_first_name" from "person" group by "g" order by "g"', - parameters: [], - }, - mysql: { - sql: 'select `gender` as `g`, max(first_name) as `max_first_name` from `person` group by `g` order by `g`', - parameters: [], - }, - sqlite: { - sql: 'select "gender" as "g", max(first_name) as "max_first_name" from "person" group by "g" order by "g"', - parameters: [], - }, - }) + testSql(query, dialect, { + postgres: { + sql: 'select "gender" as "g", max(first_name) as "max_first_name" from "person" group by "g" order by "g"', + parameters: [], + }, + mysql: { + sql: 'select `gender` as `g`, max(first_name) as `max_first_name` from `person` group by `g` order by `g`', + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'select "gender" as "g", max(first_name) as "max_first_name" from "person" group by "g" order by "g"', + parameters: [], + }, + }) - const persons = await query.execute() + const persons = await query.execute() - expect(persons).to.have.length(2) - expect(persons).to.containSubset([ - { - max_first_name: 'Jennifer', - g: 'female', - }, - { - max_first_name: 'Sylvester', - g: 'male', - }, - ]) - }) + expect(persons).to.have.length(2) + expect(persons).to.containSubset([ + { + max_first_name: 'Jennifer', + g: 'female', + }, + { + max_first_name: 'Sylvester', + g: 'male', + }, + ]) + }) + } it('group by two columns', async () => { const query = ctx.db @@ -121,6 +129,10 @@ for (const dialect of DIALECTS) { sql: 'select `gender`, max(first_name) as `max_first_name` from `person` group by `gender`, `id` order by `gender`', parameters: [], }, + mssql: { + sql: 'select "gender", max(first_name) as "max_first_name" from "person" group by "gender", "id" order by "gender"', + parameters: [], + }, sqlite: { sql: 'select "gender", max(first_name) as "max_first_name" from "person" group by "gender", "id" order by "gender"', parameters: [], @@ -146,6 +158,10 @@ for (const dialect of DIALECTS) { sql: 'select `gender`, max(first_name) as `max_first_name` from `person` group by `person`.`gender` order by `gender` asc', parameters: [], }, + mssql: { + sql: 'select "gender", max(first_name) as "max_first_name" from "person" group by "person"."gender" order by "gender" asc', + parameters: [], + }, sqlite: { sql: 'select "gender", max(first_name) as "max_first_name" from "person" group by "person"."gender" order by "gender" asc', parameters: [], @@ -171,6 +187,10 @@ for (const dialect of DIALECTS) { sql: 'select `gender`, max(first_name) as `max_first_name` from `person` group by person.gender order by `gender` asc', parameters: [], }, + mssql: { + sql: 'select "gender", max(first_name) as "max_first_name" from "person" group by person.gender order by "gender" asc', + parameters: [], + }, sqlite: { sql: 'select "gender", max(first_name) as "max_first_name" from "person" group by person.gender order by "gender" asc', parameters: [], @@ -180,50 +200,61 @@ for (const dialect of DIALECTS) { await query.execute() }) - it('group by a sub query', async () => { - const query = ctx.db - .selectFrom('person') - .select(sql`max(first_name)`.as('max_first_name')) - .groupBy((qb) => - qb - .selectFrom('pet') - .whereRef('person.id', '=', 'pet.owner_id') - .select('pet.name') - ) - .orderBy('max_first_name') + if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'sqlite') { + it('group by a sub query', async () => { + const query = ctx.db + .selectFrom('person') + .select(sql`max(first_name)`.as('max_first_name')) + .groupBy((qb) => + qb + .selectFrom('pet') + .whereRef('person.id', '=', 'pet.owner_id') + .select('pet.name'), + ) + .orderBy('max_first_name') - testSql(query, dialect, { - postgres: { - sql: [ - 'select max(first_name) as "max_first_name"', - 'from "person"', - 'group by (select "pet"."name" from "pet" where "person"."id" = "pet"."owner_id")', - 'order by "max_first_name"', - ], - parameters: [], - }, - mysql: { - sql: [ - 'select max(first_name) as `max_first_name`', - 'from `person`', - 'group by (select `pet`.`name` from `pet` where `person`.`id` = `pet`.`owner_id`)', - 'order by `max_first_name`', - ], - parameters: [], - }, - sqlite: { - sql: [ - 'select max(first_name) as "max_first_name"', - 'from "person"', - 'group by (select "pet"."name" from "pet" where "person"."id" = "pet"."owner_id")', - 'order by "max_first_name"', - ], - parameters: [], - }, - }) + testSql(query, dialect, { + postgres: { + sql: [ + 'select max(first_name) as "max_first_name"', + 'from "person"', + 'group by (select "pet"."name" from "pet" where "person"."id" = "pet"."owner_id")', + 'order by "max_first_name"', + ], + parameters: [], + }, + mysql: { + sql: [ + 'select max(first_name) as `max_first_name`', + 'from `person`', + 'group by (select `pet`.`name` from `pet` where `person`.`id` = `pet`.`owner_id`)', + 'order by `max_first_name`', + ], + parameters: [], + }, + mssql: { + sql: [ + 'select max(first_name) as "max_first_name"', + 'from "person"', + 'group by (select "pet"."name" from "pet" where "person"."id" = "pet"."owner_id")', + 'order by "max_first_name"', + ], + parameters: [], + }, + sqlite: { + sql: [ + 'select max(first_name) as "max_first_name"', + 'from "person"', + 'group by (select "pet"."name" from "pet" where "person"."id" = "pet"."owner_id")', + 'order by "max_first_name"', + ], + parameters: [], + }, + }) - await query.execute() - }) + await query.execute() + }) + } it('conditional group by', async () => { const filterByPetCount = true @@ -249,7 +280,7 @@ for (const dialect of DIALECTS) { qb .innerJoin('pet', 'pet.owner_id', 'person.id') .having(count('pet.id'), '>', 1) - .groupBy('person.first_name') + .groupBy('person.first_name'), ) .execute() diff --git a/test/node/src/having.test.ts b/test/node/src/having.test.ts index ae2defeb6..4c7a38c63 100644 --- a/test/node/src/having.test.ts +++ b/test/node/src/having.test.ts @@ -1,7 +1,6 @@ import { sql } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -9,6 +8,7 @@ import { TestContext, testSql, expect, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -87,6 +87,16 @@ for (const dialect of DIALECTS) { ], parameters: [1], }, + mssql: { + sql: [ + `select "first_name", count(pet.id) as "num_pets"`, + `from "person"`, + `inner join "pet" on "pet"."owner_id" = "person"."id"`, + `group by "first_name"`, + `having count(pet.id) > @1`, + ], + parameters: [1], + }, sqlite: { sql: [ `select "first_name", count(pet.id) as "num_pets"`, @@ -102,7 +112,7 @@ for (const dialect of DIALECTS) { const result = await query.execute() expect(result).to.have.length(2) - if (dialect === 'sqlite') { + if (dialect === 'mssql' || dialect === 'sqlite') { expect(result).to.containSubset([ { first_name: 'Jennifer', num_pets: 2 }, { first_name: 'Arnold', num_pets: 2 }, @@ -146,6 +156,16 @@ for (const dialect of DIALECTS) { ], parameters: [1], }, + mssql: { + sql: [ + `select "person"."id", count("pet"."id") as "num_pets"`, + `from "person"`, + `inner join "pet" on "pet"."owner_id" = "person"."id"`, + `group by "person"."id"`, + `having count("pet"."id") > @1`, + ], + parameters: [1], + }, sqlite: { sql: [ `select "person"."id", count("pet"."id") as "num_pets"`, @@ -161,7 +181,7 @@ for (const dialect of DIALECTS) { const result = await query.execute() expect(result).to.have.length(2) - if (dialect === 'sqlite') { + if (dialect === 'mssql' || dialect === 'sqlite') { expect(result).to.containSubset([{ num_pets: 2 }, { num_pets: 2 }]) } else { expect(result).to.containSubset([{ num_pets: '2' }, { num_pets: '2' }]) @@ -173,68 +193,32 @@ for (const dialect of DIALECTS) { .selectFrom('person') .selectAll() .groupBy('first_name') - .having('id', 'in', [1, 2, 3]) - .orHaving('first_name', '<', 'foo') + .having((eb) => + eb.or([ + eb('id', 'in', [1, 2, 3]), + eb('first_name', '<', 'foo'), + eb('first_name', '=', eb.ref('first_name')), + ]), + ) .havingRef('first_name', '=', 'first_name') - .orHavingRef('first_name', '=', 'first_name') - .havingExists((qb) => qb.selectFrom('pet').select('id')) - .orHavingExists((qb) => qb.selectFrom('pet').select('id')) - .havingNotExist((qb) => qb.selectFrom('pet').select('id')) - .orHavingNotExists((qb) => qb.selectFrom('pet').select('id')) - .having((qb) => qb.having('id', '=', 1).orHaving('id', '=', 2)) - .having(({ or, cmpr }) => or([cmpr('id', '=', 1), cmpr('id', '=', 2)])) + .having((eb) => eb.not(eb.exists(eb.selectFrom('pet').select('id')))) testSql(query, dialect, { postgres: { - sql: [ - `select * from "person"`, - `group by "first_name"`, - `having "id" in ($1, $2, $3)`, - `or "first_name" < $4`, - `and "first_name" = "first_name"`, - `or "first_name" = "first_name"`, - `and exists (select "id" from "pet")`, - `or exists (select "id" from "pet")`, - `and not exists (select "id" from "pet")`, - `or not exists (select "id" from "pet")`, - 'and ("id" = $5 or "id" = $6)', - 'and ("id" = $7 or "id" = $8)', - ], - parameters: [1, 2, 3, 'foo', 1, 2, 1, 2], + sql: `select * from "person" group by "first_name" having ("id" in ($1, $2, $3) or "first_name" < $4 or "first_name" = "first_name") and "first_name" = "first_name" and not exists (select "id" from "pet")`, + parameters: [1, 2, 3, 'foo'], }, mysql: { - sql: [ - 'select * from `person`', - 'group by `first_name`', - 'having `id` in (?, ?, ?)', - 'or `first_name` < ?', - 'and `first_name` = `first_name`', - 'or `first_name` = `first_name`', - 'and exists (select `id` from `pet`)', - 'or exists (select `id` from `pet`)', - 'and not exists (select `id` from `pet`)', - 'or not exists (select `id` from `pet`)', - 'and (`id` = ? or `id` = ?)', - 'and (`id` = ? or `id` = ?)', - ], - parameters: [1, 2, 3, 'foo', 1, 2, 1, 2], + sql: 'select * from `person` group by `first_name` having (`id` in (?, ?, ?) or `first_name` < ? or `first_name` = `first_name`) and `first_name` = `first_name` and not exists (select `id` from `pet`)', + parameters: [1, 2, 3, 'foo'], + }, + mssql: { + sql: `select * from "person" group by "first_name" having ("id" in (@1, @2, @3) or "first_name" < @4 or "first_name" = "first_name") and "first_name" = "first_name" and not exists (select "id" from "pet")`, + parameters: [1, 2, 3, 'foo'], }, sqlite: { - sql: [ - `select * from "person"`, - `group by "first_name"`, - `having "id" in (?, ?, ?)`, - `or "first_name" < ?`, - `and "first_name" = "first_name"`, - `or "first_name" = "first_name"`, - `and exists (select "id" from "pet")`, - `or exists (select "id" from "pet")`, - `and not exists (select "id" from "pet")`, - `or not exists (select "id" from "pet")`, - 'and ("id" = ? or "id" = ?)', - 'and ("id" = ? or "id" = ?)', - ], - parameters: [1, 2, 3, 'foo', 1, 2, 1, 2], + sql: `select * from "person" group by "first_name" having ("id" in (?, ?, ?) or "first_name" < ? or "first_name" = "first_name") and "first_name" = "first_name" and not exists (select "id" from "pet")`, + parameters: [1, 2, 3, 'foo'], }, }) }) diff --git a/test/node/src/insert.test.ts b/test/node/src/insert.test.ts index dd26bf556..2b69a6c09 100644 --- a/test/node/src/insert.test.ts +++ b/test/node/src/insert.test.ts @@ -1,7 +1,6 @@ import { AliasedRawBuilder, InsertResult, Kysely, sql } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -12,6 +11,8 @@ import { Database, NOT_SUPPORTED, insertDefaultDataSet, + DIALECTS, + limit, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -50,6 +51,10 @@ for (const dialect of DIALECTS) { sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)', parameters: ['Foo', 'Barson', 'other'], }, + mssql: { + sql: 'insert into "person" ("first_name", "last_name", "gender") values (@1, @2, @3)', + parameters: ['Foo', 'Barson', 'other'], + }, sqlite: { sql: 'insert into "person" ("first_name", "last_name", "gender") values (?, ?, ?)', parameters: ['Foo', 'Barson', 'other'], @@ -60,7 +65,7 @@ for (const dialect of DIALECTS) { expect(result).to.be.instanceOf(InsertResult) expect(result.numInsertedOrUpdatedRows).to.equal(1n) - if (dialect === 'postgres') { + if (dialect === 'postgres' || dialect === 'mssql') { expect(result.insertId).to.be.undefined } else { expect(result.insertId).to.be.a('bigint') @@ -72,6 +77,29 @@ for (const dialect of DIALECTS) { }) }) + it('should insert one row with default values', async () => { + const query = ctx.db.insertInto('person').defaultValues() + + testSql(query, dialect, { + postgres: { + sql: 'insert into "person" default values', + parameters: [], + }, + mysql: { + sql: 'insert into `person` default values', + parameters: [], + }, + mssql: { + sql: 'insert into "person" default values', + parameters: [], + }, + sqlite: { + sql: 'insert into "person" default values', + parameters: [], + }, + }) + }) + it('should insert one row with complex values', async () => { const query = ctx.db.insertInto('person').values({ first_name: ctx.db @@ -93,6 +121,10 @@ for (const dialect of DIALECTS) { sql: "insert into `person` (`first_name`, `last_name`, `gender`) values ((select max(name) as `max_name` from `pet`), concat('Bar', 'son'), ?)", parameters: ['other'], }, + mssql: { + sql: `insert into "person" ("first_name", "last_name", "gender") values ((select max(name) as "max_name" from "pet"), concat('Bar', 'son'), @1)`, + parameters: ['other'], + }, sqlite: { sql: `insert into "person" ("first_name", "last_name", "gender") values ((select max(name) as "max_name" from "pet"), 'Bar' || 'son', ?)`, parameters: ['other'], @@ -109,46 +141,49 @@ for (const dialect of DIALECTS) { }) }) - it.skip('should insert one row with expressions', async () => { - const query = ctx.db.insertInto('person').values(({ selectFrom }) => ({ - first_name: selectFrom('pet') - .select('name') - .where('species', '=', 'dog') - .limit(1), - gender: 'female', - })) + if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'sqlite') { + it('should insert one row with expressions', async () => { + const query = ctx.db.insertInto('person').values(({ selectFrom }) => ({ + first_name: selectFrom('pet') + .select('name') + .where('species', '=', 'dog') + .limit(1), + gender: 'female', + })) - testSql(query, dialect, { - postgres: { - sql: `insert into "person" ("first_name", "gender") values ((select "first_name" from "person" where "last_name" = $1 limit $2), $3)`, - parameters: ['Aniston', 1, 'female'], - }, - mysql: { - sql: 'insert into `person` (`first_name`, `gender`) values ((select `first_name` from `person` where `last_name` = ? limit ?), ?)', - parameters: ['Aniston', 1, 'female'], - }, - sqlite: { - sql: `insert into "person" ("first_name", "gender") values ((select "first_name" from "person" where "last_name" = ? limit ?), ?)`, - parameters: ['Aniston', 1, 'female'], - }, - }) + testSql(query, dialect, { + postgres: { + sql: `insert into "person" ("first_name", "gender") values ((select "name" from "pet" where "species" = $1 limit $2), $3)`, + parameters: ['dog', 1, 'female'], + }, + mysql: { + sql: 'insert into `person` (`first_name`, `gender`) values ((select `name` from `pet` where `species` = ? limit ?), ?)', + parameters: ['dog', 1, 'female'], + }, + sqlite: { + sql: `insert into "person" ("first_name", "gender") values ((select "name" from "pet" where "species" = ? limit ?), ?)`, + parameters: ['dog', 1, 'female'], + }, + mssql: NOT_SUPPORTED, + }) - const result = await query.executeTakeFirst() - expect(result).to.be.instanceOf(InsertResult) - expect(result.numInsertedOrUpdatedRows).to.equal(1n) + const result = await query.executeTakeFirst() + expect(result).to.be.instanceOf(InsertResult) + expect(result.numInsertedOrUpdatedRows).to.equal(1n) - expect(await getNewestPerson(ctx.db)).to.eql({ - first_name: 'Jennifer', - last_name: null, + expect(await getNewestPerson(ctx.db)).to.eql({ + first_name: 'Doggo', + last_name: null, + }) }) - }) + } it('should insert the result of a select query', async () => { const query = ctx.db .insertInto('person') .columns(['first_name', 'gender']) .expression((eb) => - eb.selectFrom('pet').select(['name', sql`${'other'}`.as('gender')]) + eb.selectFrom('pet').select(['name', eb.val('other').as('gender')]), ) testSql(query, dialect, { @@ -160,6 +195,10 @@ for (const dialect of DIALECTS) { sql: 'insert into `person` (`first_name`, `gender`) select `name`, ? as `gender` from `pet`', parameters: ['other'], }, + mssql: { + sql: 'insert into "person" ("first_name", "gender") select "name", @1 as "gender" from "pet"', + parameters: ['other'], + }, sqlite: { sql: 'insert into "person" ("first_name", "gender") select "name", ? as "gender" from "pet"', parameters: ['other'], @@ -192,7 +231,7 @@ for (const dialect of DIALECTS) { ]) }) - if (dialect === 'postgres') { + if (dialect === 'postgres' || dialect === 'mssql') { it('should insert the result of a values expression', async () => { const query = ctx.db .insertInto('person') @@ -205,12 +244,16 @@ for (const dialect of DIALECTS) { { a: 1, b: 'foo' }, { a: 2, b: 'bar' }, ], - 't' - ) + 't', + ), ) - .select(['t.a', 't.b']) + .select(['t.a', 't.b']), + ) + .$call((qb) => + dialect === 'postgres' + ? qb.returning(['first_name', 'gender']) + : qb.output(['inserted.first_name', 'inserted.gender']), ) - .returning(['first_name', 'gender']) testSql(query, dialect, { postgres: { @@ -218,6 +261,10 @@ for (const dialect of DIALECTS) { parameters: [1, 'foo', 2, 'bar'], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'insert into "person" ("first_name", "gender") output "inserted"."first_name", "inserted"."gender" select "t"."a", "t"."b" from (values (@1, @2), (@3, @4)) as t(a, b)', + parameters: [1, 'foo', 2, 'bar'], + }, sqlite: NOT_SUPPORTED, }) @@ -248,6 +295,10 @@ for (const dialect of DIALECTS) { sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)', parameters: ['Foo', 'Barson', 'other'], }, + mssql: { + sql: 'insert into "person" ("first_name", "last_name", "gender") values (@1, @2, @3)', + parameters: ['Foo', 'Barson', 'other'], + }, sqlite: { sql: 'insert into "person" ("first_name", "last_name", "gender") values (?, ?, ?)', parameters: ['Foo', 'Barson', 'other'], @@ -259,7 +310,7 @@ for (const dialect of DIALECTS) { expect(result).to.be.instanceOf(InsertResult) expect(result.numInsertedOrUpdatedRows).to.equal(1n) - if (dialect === 'postgres') { + if (dialect === 'postgres' || dialect === 'mssql') { expect(result.insertId).to.be.undefined } else { expect(result.insertId).to.be.a('bigint') @@ -286,6 +337,7 @@ for (const dialect of DIALECTS) { ], }, postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -297,7 +349,7 @@ for (const dialect of DIALECTS) { }) } - if (dialect !== 'mysql') { + if (dialect === 'postgres' || dialect === 'sqlite') { it('should insert one row and ignore conflicts using `on conflict do nothing`', async () => { const [{ id, ...existingPet }] = await ctx.db .selectFrom('pet') @@ -319,6 +371,7 @@ for (const dialect of DIALECTS) { existingPet.species, ], }, + mssql: NOT_SUPPORTED, sqlite: { sql: 'insert into "pet" ("name", "owner_id", "species") values (?, ?, ?) on conflict ("name") do nothing', parameters: [ @@ -367,6 +420,7 @@ for (const dialect of DIALECTS) { ], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -402,6 +456,7 @@ for (const dialect of DIALECTS) { ], }, postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -424,7 +479,7 @@ for (const dialect of DIALECTS) { }) } - if (dialect !== 'mysql') { + if (dialect === 'postgres' || dialect === 'sqlite') { it('should update instead of insert on conflict when using `on conflict do update`', async () => { const [{ id, ...existingPet }] = await ctx.db .selectFrom('pet') @@ -436,7 +491,7 @@ for (const dialect of DIALECTS) { .insertInto('pet') .values(existingPet) .onConflict((oc) => - oc.columns(['name']).doUpdateSet({ species: 'hamster' }) + oc.columns(['name']).doUpdateSet({ species: 'hamster' }), ) testSql(query, dialect, { @@ -450,6 +505,7 @@ for (const dialect of DIALECTS) { ], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: 'insert into "pet" ("name", "owner_id", "species") values (?, ?, ?) on conflict ("name") do update set "species" = ?', parameters: [ @@ -497,7 +553,7 @@ for (const dialect of DIALECTS) { .insertInto('pet') .values(existingPet) .onConflict((oc) => - oc.constraint('pet_name_key').doUpdateSet({ species: 'hamster' }) + oc.constraint('pet_name_key').doUpdateSet({ species: 'hamster' }), ) .returningAll() @@ -512,6 +568,7 @@ for (const dialect of DIALECTS) { ], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -541,7 +598,7 @@ for (const dialect of DIALECTS) { species: 'hamster', name: (eb) => eb.ref('excluded.name'), }) - .where('excluded.name', '!=', 'Doggo') + .where('excluded.name', '!=', 'Doggo'), ) .returningAll() @@ -558,6 +615,7 @@ for (const dialect of DIALECTS) { ], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -594,6 +652,10 @@ for (const dialect of DIALECTS) { sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?), (?, ?, ?)', parameters: ['Foo', 'Bar', 'other', 'Baz', 'Spam', 'other'], }, + mssql: { + sql: 'insert into "person" ("first_name", "last_name", "gender") values (@1, @2, @3), (@4, @5, @6)', + parameters: ['Foo', 'Bar', 'other', 'Baz', 'Spam', 'other'], + }, sqlite: { sql: 'insert into "person" ("first_name", "last_name", "gender") values (?, ?, ?), (?, ?, ?)', parameters: ['Foo', 'Bar', 'other', 'Baz', 'Spam', 'other'], @@ -605,7 +667,7 @@ for (const dialect of DIALECTS) { expect(result).to.be.instanceOf(InsertResult) expect(result.numInsertedOrUpdatedRows).to.equal(2n) - if (dialect === 'postgres') { + if (dialect === 'postgres' || dialect === 'mssql') { expect(result.insertId).to.be.undefined } else { expect(result.insertId).to.be.a('bigint') @@ -615,7 +677,7 @@ for (const dialect of DIALECTS) { .selectFrom('person') .selectAll() .orderBy('id', 'desc') - .limit(2) + .$call(limit(2, dialect)) .execute() expect(inserted).to.containSubset([ @@ -649,6 +711,10 @@ for (const dialect of DIALECTS) { sql: 'insert into `person` (`first_name`, `gender`, `last_name`, `middle_name`) values (?, ?, default, default), (?, ?, ?, ?)', parameters: ['Foo', 'other', 'Baz', 'other', 'Spam', 'Bo'], }, + mssql: { + sql: 'insert into "person" ("first_name", "gender", "last_name", "middle_name") values (@1, @2, default, default), (@3, @4, @5, @6)', + parameters: ['Foo', 'other', 'Baz', 'other', 'Spam', 'Bo'], + }, sqlite: { sql: 'insert into "person" ("first_name", "gender", "last_name", "middle_name") values (?, ?, null, null), (?, ?, ?, ?)', parameters: ['Foo', 'other', 'Baz', 'other', 'Spam', 'Bo'], @@ -683,6 +749,10 @@ for (const dialect of DIALECTS) { sql: 'insert into `person` (`first_name`, `last_name`, `middle_name`, `gender`) values (?, ?, ?, ?), (?, default, default, ?)', parameters: ['Foo', 'Spam', 'Bo', 'other', 'Baz', 'other'], }, + mssql: { + sql: 'insert into "person" ("first_name", "last_name", "middle_name", "gender") values (@1, @2, @3, @4), (@5, default, default, @6)', + parameters: ['Foo', 'Spam', 'Bo', 'other', 'Baz', 'other'], + }, sqlite: { sql: 'insert into "person" ("first_name", "last_name", "middle_name", "gender") values (?, ?, ?, ?), (?, null, null, ?)', parameters: ['Foo', 'Spam', 'Bo', 'other', 'Baz', 'other'], @@ -717,6 +787,10 @@ for (const dialect of DIALECTS) { sql: 'insert into `person` (`first_name`, `middle_name`, `gender`, `last_name`) values (?, ?, ?, default), (?, default, ?, ?)', parameters: ['Foo', 'Bo', 'other', 'Baz', 'other', 'Spam'], }, + mssql: { + sql: 'insert into "person" ("first_name", "middle_name", "gender", "last_name") values (@1, @2, @3, default), (@4, default, @5, @6)', + parameters: ['Foo', 'Bo', 'other', 'Baz', 'other', 'Spam'], + }, sqlite: { sql: 'insert into "person" ("first_name", "middle_name", "gender", "last_name") values (?, ?, ?, null), (?, null, ?, ?)', parameters: ['Foo', 'Bo', 'other', 'Baz', 'other', 'Spam'], @@ -753,24 +827,24 @@ for (const dialect of DIALECTS) { first_name: 'Sylvester', last_name: 'Barson', }) + }) - it('should insert a row, returning some fields of inserted row and conditionally returning additional fields', async () => { - const condition = true + it('should insert a row, returning some fields of inserted row and conditionally returning additional fields', async () => { + const condition = true - const query = ctx.db - .insertInto('person') - .values({ - first_name: 'Foo', - last_name: 'Barson', - gender: 'other', - }) - .returning('first_name') - .$if(condition, (qb) => qb.returning('last_name')) + const query = ctx.db + .insertInto('person') + .values({ + first_name: 'Foo', + last_name: 'Barson', + gender: 'other', + }) + .returning('first_name') + .$if(condition, (qb) => qb.returning('last_name')) - const result = await query.executeTakeFirstOrThrow() + const result = await query.executeTakeFirstOrThrow() - expect(result.last_name).to.equal('Barson') - }) + expect(result.last_name).to.equal('Barson') }) it('should insert a row and return data using `returningAll`', async () => { @@ -833,10 +907,130 @@ for (const dialect of DIALECTS) { expect(people).to.eql(values) }) } + + if (dialect === 'mssql') { + it('should insert top', async () => { + const query = ctx.db + .insertInto('person') + .top(1) + .columns(['first_name', 'gender']) + .expression((eb) => + eb.selectFrom('pet').select(['name', eb.val('other').as('gender')]), + ) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'insert top(1) into "person" ("first_name", "gender") select "name", @1 as "gender" from "pet"', + parameters: ['other'], + }, + sqlite: NOT_SUPPORTED, + }) + + await query.executeTakeFirstOrThrow() + }) + + it('should insert top percent', async () => { + const query = ctx.db + .insertInto('person') + .top(50, 'percent') + .columns(['first_name', 'gender']) + .expression((eb) => + eb.selectFrom('pet').select(['name', eb.val('other').as('gender')]), + ) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'insert top(50) percent into "person" ("first_name", "gender") select "name", @1 as "gender" from "pet"', + parameters: ['other'], + }, + sqlite: NOT_SUPPORTED, + }) + + await query.executeTakeFirstOrThrow() + }) + } + + if (dialect === 'mssql') { + it('should insert a row and return data using `output`', async () => { + const result = await ctx.db + .insertInto('person') + .output([ + 'inserted.first_name', + 'inserted.last_name', + 'inserted.gender', + ]) + .values({ + gender: 'other', + first_name: ctx.db + .selectFrom('person') + .select(sql`max(first_name)`.as('max_first_name')), + last_name: sql`concat(cast(${'Bar'} as varchar), cast(${'son'} as varchar))`, + }) + .executeTakeFirst() + + expect(result).to.eql({ + first_name: 'Sylvester', + last_name: 'Barson', + gender: 'other', + }) + + expect(await getNewestPerson(ctx.db)).to.eql({ + first_name: 'Sylvester', + last_name: 'Barson', + }) + }) + + it('should insert a row, returning some fields of inserted row and conditionally returning additional fields', async () => { + const condition = true + + const query = ctx.db + .insertInto('person') + .output('inserted.first_name') + .$if(condition, (qb) => qb.output('inserted.last_name')) + .values({ + first_name: 'Foo', + last_name: 'Barson', + gender: 'other', + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result.last_name).to.equal('Barson') + }) + + it('should insert a row and return data using `outputAll`', async () => { + const result = await ctx.db + .insertInto('person') + .outputAll('inserted') + .values({ + gender: 'other', + first_name: ctx.db + .selectFrom('person') + .select(sql`max(first_name)`.as('max_first_name')), + last_name: sql`concat(cast(${'Bar'} as varchar), cast(${'son'} as varchar))`, + }) + .executeTakeFirst() + + expect(result).to.containSubset({ + first_name: 'Sylvester', + last_name: 'Barson', + gender: 'other', + }) + + expect(await getNewestPerson(ctx.db)).to.eql({ + first_name: 'Sylvester', + last_name: 'Barson', + }) + }) + } }) async function getNewestPerson( - db: Kysely + db: Kysely, ): Promise | undefined> { return await db .selectFrom('person') @@ -844,7 +1038,7 @@ for (const dialect of DIALECTS) { .where( 'id', '=', - db.selectFrom('person').select(sql`max(id)`.as('max_id')) + db.selectFrom('person').select(sql`max(id)`.as('max_id')), ) .executeTakeFirst() } @@ -852,7 +1046,7 @@ for (const dialect of DIALECTS) { function values, A extends string>( records: R[], - alias: A + alias: A, ): AliasedRawBuilder { const keys = Object.keys(records[0]) @@ -860,10 +1054,10 @@ function values, A extends string>( records.map((r) => { const v = sql.join(keys.map((k) => sql`${r[k]}`)) return sql`(${v})` - }) + }), ) return sql`(values ${values})`.as( - sql.raw(`${alias}(${keys.join(', ')})`) + sql.raw(`${alias}(${keys.join(', ')})`), ) } diff --git a/test/node/src/introspect.test.ts b/test/node/src/introspect.test.ts index 56a8bfe2f..86e1a6cac 100644 --- a/test/node/src/introspect.test.ts +++ b/test/node/src/introspect.test.ts @@ -1,12 +1,12 @@ import { sql } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, TestContext, expect, insertDefaultDataSet, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -16,7 +16,7 @@ for (const dialect of DIALECTS) { before(async function () { ctx = await initTest(this, dialect) - if (dialect === 'postgres') { + if (dialect === 'postgres' || dialect === 'mssql') { await dropSchema() await createSchema() } @@ -42,455 +42,763 @@ for (const dialect of DIALECTS) { await destroyTest(ctx) }) - it('should get table metadata', async () => { - const meta = await ctx.db.introspection.getTables() + describe('getSchemas', () => { + it('should get schema names', async () => { + const schemas = await ctx.db.introspection.getSchemas() - if (dialect === 'postgres') { - expect(meta).to.eql([ - { - name: 'person', - isView: false, - schema: 'public', - columns: [ - { - name: 'id', - dataType: 'int4', - dataTypeSchema: 'pg_catalog', - isNullable: false, - isAutoIncrementing: true, - hasDefaultValue: true, - }, - { - name: 'first_name', - dataType: 'varchar', - dataTypeSchema: 'pg_catalog', - isNullable: true, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'middle_name', - dataType: 'varchar', - dataTypeSchema: 'pg_catalog', - isNullable: true, - isAutoIncrementing: false, - hasDefaultValue: false, - }, + if (dialect === 'postgres') { + expect(schemas).to.containSubset([ + { name: 'public' }, + { name: 'information_schema' }, + { name: 'pg_catalog' }, + { name: 'some_schema' }, + { name: 'dtype_schema' }, + ]) + } else if (dialect === 'mysql') { + expect(schemas).to.containSubset([ + { name: 'mysql' }, + { name: 'information_schema' }, + { name: 'performance_schema' }, + { name: 'sys' }, + { name: 'kysely_test' }, + ]) + } else if (dialect === 'mssql') { + expect(schemas).to.containSubset([ + { name: 'dbo' }, + { name: 'sys' }, + { name: 'guest' }, + { name: 'INFORMATION_SCHEMA' }, + { name: 'some_schema' }, + ]) + } else if (dialect === 'sqlite') { + expect(schemas).to.eql([]) + } + }) + }) - { - name: 'last_name', - dataType: 'varchar', - dataTypeSchema: 'pg_catalog', - isNullable: true, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'gender', - dataType: 'varchar', - dataTypeSchema: 'pg_catalog', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'marital_status', - dataType: 'varchar', - dataTypeSchema: 'pg_catalog', - isNullable: true, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - ], - }, - { - name: 'pet', - isView: false, - schema: 'public', - columns: [ - { - name: 'id', - dataType: 'int4', - dataTypeSchema: 'pg_catalog', - isNullable: false, - isAutoIncrementing: true, - hasDefaultValue: true, - }, - { - name: 'name', - dataType: 'varchar', - dataTypeSchema: 'pg_catalog', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'owner_id', - dataType: 'int4', - dataTypeSchema: 'pg_catalog', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'species', - dataType: 'varchar', - dataTypeSchema: 'pg_catalog', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - ], - }, - { - name: 'toy', - isView: false, - schema: 'public', - columns: [ - { - name: 'id', - dataType: 'int4', - dataTypeSchema: 'pg_catalog', - isNullable: false, - isAutoIncrementing: true, - hasDefaultValue: true, - }, - { - name: 'name', - dataType: 'varchar', - dataTypeSchema: 'pg_catalog', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'pet_id', - dataType: 'int4', - dataTypeSchema: 'pg_catalog', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'price', - dataType: 'float8', - dataTypeSchema: 'pg_catalog', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - ], - }, - { - name: 'toy_names', - isView: true, - schema: 'public', - columns: [ - { - name: 'name', - dataType: 'varchar', - dataTypeSchema: 'pg_catalog', - isNullable: true, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - ], - }, - { - name: 'pet', - isView: false, - schema: 'some_schema', - columns: [ - { - name: 'some_column', - dataType: 'int4', - dataTypeSchema: 'pg_catalog', - isNullable: false, - isAutoIncrementing: true, - hasDefaultValue: true, - }, - { - dataType: 'species', - dataTypeSchema: 'dtype_schema', - hasDefaultValue: false, - isAutoIncrementing: false, - isNullable: true, - name: 'spcies', - }, - ], - }, - ]) - } else if (dialect === 'mysql') { - expect(meta).to.eql([ - { - name: 'person', - isView: false, - schema: 'kysely_test', - columns: [ - { - name: 'id', - dataType: 'int', - isNullable: false, - isAutoIncrementing: true, - hasDefaultValue: false, - }, - { - name: 'first_name', - dataType: 'varchar', - isNullable: true, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'middle_name', - dataType: 'varchar', - isNullable: true, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'last_name', - dataType: 'varchar', - isNullable: true, - isAutoIncrementing: false, - hasDefaultValue: false, - }, + describe('getTables', () => { + it('should get table metadata', async () => { + const meta = await ctx.db.introspection.getTables() - { - name: 'gender', - dataType: 'varchar', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'marital_status', - dataType: 'varchar', - isNullable: true, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - ], - }, - { - name: 'pet', - isView: false, - schema: 'kysely_test', - columns: [ - { - name: 'id', - dataType: 'int', - isNullable: false, - isAutoIncrementing: true, - hasDefaultValue: false, - }, - { - name: 'name', - dataType: 'varchar', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'owner_id', - dataType: 'int', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'species', - dataType: 'varchar', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - ], - }, - { - name: 'toy', - isView: false, - schema: 'kysely_test', - columns: [ - { - name: 'id', - dataType: 'int', - isNullable: false, - isAutoIncrementing: true, - hasDefaultValue: false, - }, - { - name: 'name', - dataType: 'varchar', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'pet_id', - dataType: 'int', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'price', - dataType: 'double', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - ], - }, - { - name: 'toy_names', - isView: true, - schema: 'kysely_test', - columns: [ - { - dataType: 'varchar', - hasDefaultValue: false, - isAutoIncrementing: false, - isNullable: false, - name: 'name', - }, - ], - }, - ]) - } else if (dialect === 'sqlite') { - expect(meta).to.eql([ - { - name: 'person', - isView: false, - columns: [ - { - name: 'id', - dataType: 'INTEGER', - isNullable: true, - isAutoIncrementing: true, - hasDefaultValue: false, - }, - { - name: 'first_name', - dataType: 'varchar(255)', - isNullable: true, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'middle_name', - dataType: 'varchar(255)', - isNullable: true, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'last_name', - dataType: 'varchar(255)', - isNullable: true, - isAutoIncrementing: false, - hasDefaultValue: false, - }, + if (dialect === 'postgres') { + expect(meta).to.eql([ + { + name: 'person', + isView: false, + schema: 'public', + columns: [ + { + name: 'id', + dataType: 'int4', + dataTypeSchema: 'pg_catalog', + isNullable: false, + isAutoIncrementing: true, + hasDefaultValue: true, + comment: undefined, + }, + { + name: 'first_name', + dataType: 'varchar', + dataTypeSchema: 'pg_catalog', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'middle_name', + dataType: 'varchar', + dataTypeSchema: 'pg_catalog', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, - { - name: 'gender', - dataType: 'varchar(50)', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'marital_status', - dataType: 'varchar(50)', - isNullable: true, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - ], - }, - { - name: 'pet', - isView: false, - columns: [ - { - name: 'id', - dataType: 'INTEGER', - isNullable: true, - isAutoIncrementing: true, - hasDefaultValue: false, - }, - { - name: 'name', - dataType: 'varchar(255)', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'owner_id', - dataType: 'INTEGER', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'species', - dataType: 'varchar(50)', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - ], - }, - { - name: 'toy', - isView: false, - columns: [ - { - name: 'id', - dataType: 'INTEGER', - isNullable: true, - isAutoIncrementing: true, - hasDefaultValue: false, - }, - { - name: 'name', - dataType: 'varchar(255)', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'pet_id', - dataType: 'INTEGER', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - { - name: 'price', - dataType: 'double precision', - isNullable: false, - isAutoIncrementing: false, - hasDefaultValue: false, - }, - ], - }, - { - name: 'toy_names', - isView: true, - columns: [ - { - dataType: 'varchar(255)', - hasDefaultValue: false, - isAutoIncrementing: false, - isNullable: true, - name: 'name', - }, - ], - }, - ]) - } + { + name: 'last_name', + dataType: 'varchar', + dataTypeSchema: 'pg_catalog', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'gender', + dataType: 'varchar', + dataTypeSchema: 'pg_catalog', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'marital_status', + dataType: 'varchar', + dataTypeSchema: 'pg_catalog', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'children', + dataType: 'int4', + dataTypeSchema: 'pg_catalog', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: true, + comment: undefined, + }, + ], + }, + { + name: 'pet', + isView: false, + schema: 'public', + columns: [ + { + name: 'id', + dataType: 'int4', + dataTypeSchema: 'pg_catalog', + isNullable: false, + isAutoIncrementing: true, + hasDefaultValue: true, + comment: undefined, + }, + { + name: 'name', + dataType: 'varchar', + dataTypeSchema: 'pg_catalog', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'owner_id', + dataType: 'int4', + dataTypeSchema: 'pg_catalog', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'species', + dataType: 'varchar', + dataTypeSchema: 'pg_catalog', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + ], + }, + { + name: 'toy', + isView: false, + schema: 'public', + columns: [ + { + name: 'id', + dataType: 'int4', + dataTypeSchema: 'pg_catalog', + isNullable: false, + isAutoIncrementing: true, + hasDefaultValue: true, + comment: undefined, + }, + { + name: 'name', + dataType: 'varchar', + dataTypeSchema: 'pg_catalog', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'pet_id', + dataType: 'int4', + dataTypeSchema: 'pg_catalog', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'price', + dataType: 'float8', + dataTypeSchema: 'pg_catalog', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: 'Price in USD', + }, + ], + }, + { + name: 'toy_names', + isView: true, + schema: 'public', + columns: [ + { + name: 'name', + dataType: 'varchar', + dataTypeSchema: 'pg_catalog', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + ], + }, + { + name: 'pet', + isView: false, + schema: 'some_schema', + columns: [ + { + name: 'some_column', + dataType: 'int4', + dataTypeSchema: 'pg_catalog', + isNullable: false, + isAutoIncrementing: true, + hasDefaultValue: true, + comment: undefined, + }, + { + dataType: 'species', + dataTypeSchema: 'dtype_schema', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: true, + name: 'spcies', + comment: undefined, + }, + ], + }, + ]) + } else if (dialect === 'mysql') { + expect(meta).to.eql([ + { + name: 'person', + isView: false, + schema: 'kysely_test', + columns: [ + { + name: 'id', + dataType: 'int', + isNullable: false, + isAutoIncrementing: true, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'first_name', + dataType: 'varchar', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'middle_name', + dataType: 'varchar', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'last_name', + dataType: 'varchar', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + + { + name: 'gender', + dataType: 'varchar', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'marital_status', + dataType: 'varchar', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'children', + dataType: 'int', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: true, + comment: undefined, + }, + ], + }, + { + name: 'pet', + isView: false, + schema: 'kysely_test', + columns: [ + { + name: 'id', + dataType: 'int', + isNullable: false, + isAutoIncrementing: true, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'name', + dataType: 'varchar', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'owner_id', + dataType: 'int', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'species', + dataType: 'varchar', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + ], + }, + { + name: 'toy', + isView: false, + schema: 'kysely_test', + columns: [ + { + name: 'id', + dataType: 'int', + isNullable: false, + isAutoIncrementing: true, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'name', + dataType: 'varchar', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'pet_id', + dataType: 'int', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'price', + dataType: 'double', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: 'Price in USD', + }, + ], + }, + { + name: 'toy_names', + isView: true, + schema: 'kysely_test', + columns: [ + { + dataType: 'varchar', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: false, + name: 'name', + comment: undefined, + }, + ], + }, + ]) + } else if (dialect === 'mssql') { + expect(meta).to.eql([ + { + isView: false, + name: 'person', + schema: 'dbo', + columns: [ + { + dataType: 'int', + dataTypeSchema: 'sys', + hasDefaultValue: true, + isAutoIncrementing: false, + isNullable: false, + name: 'children', + comment: undefined, + }, + { + dataType: 'varchar', + dataTypeSchema: 'sys', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: true, + name: 'first_name', + comment: undefined, + }, + { + dataType: 'varchar', + dataTypeSchema: 'sys', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: false, + name: 'gender', + comment: undefined, + }, + { + dataType: 'int', + dataTypeSchema: 'sys', + hasDefaultValue: true, + isAutoIncrementing: true, + isNullable: false, + name: 'id', + comment: undefined, + }, + { + dataType: 'varchar', + dataTypeSchema: 'sys', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: true, + name: 'last_name', + comment: undefined, + }, + { + dataType: 'varchar', + dataTypeSchema: 'sys', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: true, + name: 'marital_status', + comment: undefined, + }, + { + dataType: 'varchar', + dataTypeSchema: 'sys', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: true, + name: 'middle_name', + comment: undefined, + }, + ], + }, + { + isView: false, + name: 'pet', + schema: 'dbo', + columns: [ + { + dataType: 'int', + dataTypeSchema: 'sys', + hasDefaultValue: true, + isAutoIncrementing: true, + isNullable: false, + name: 'id', + comment: undefined, + }, + { + dataType: 'varchar', + dataTypeSchema: 'sys', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: false, + name: 'name', + comment: undefined, + }, + { + dataType: 'int', + dataTypeSchema: 'sys', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: false, + name: 'owner_id', + comment: undefined, + }, + { + dataType: 'varchar', + dataTypeSchema: 'sys', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: false, + name: 'species', + comment: undefined, + }, + ], + }, + { + isView: false, + name: 'toy', + schema: 'dbo', + columns: [ + { + dataType: 'int', + dataTypeSchema: 'sys', + hasDefaultValue: true, + isAutoIncrementing: true, + isNullable: false, + name: 'id', + comment: undefined, + }, + { + dataType: 'varchar', + dataTypeSchema: 'sys', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: false, + name: 'name', + comment: undefined, + }, + { + dataType: 'int', + dataTypeSchema: 'sys', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: false, + name: 'pet_id', + comment: undefined, + }, + { + dataType: 'float', + dataTypeSchema: 'sys', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: false, + name: 'price', + comment: 'Price in USD', + }, + ], + }, + { + isView: true, + name: 'toy_names', + schema: 'dbo', + columns: [ + { + dataType: 'varchar', + dataTypeSchema: 'sys', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: false, + name: 'name', + comment: undefined, + }, + ], + }, + { + isView: false, + name: 'pet', + schema: 'some_schema', + columns: [ + { + dataType: 'int', + dataTypeSchema: 'sys', + hasDefaultValue: true, + isAutoIncrementing: true, + isNullable: false, + name: 'some_column', + comment: undefined, + }, + { + dataType: 'int', + dataTypeSchema: 'sys', + hasDefaultValue: true, + isAutoIncrementing: false, + isNullable: true, + name: 'some_column_plus_1', + comment: undefined, + }, + ], + }, + ]) + } else if (dialect === 'sqlite') { + expect(meta).to.eql([ + { + name: 'person', + isView: false, + columns: [ + { + name: 'id', + dataType: 'INTEGER', + isNullable: true, + isAutoIncrementing: true, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'first_name', + dataType: 'varchar(255)', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'middle_name', + dataType: 'varchar(255)', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'last_name', + dataType: 'varchar(255)', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + + { + name: 'gender', + dataType: 'varchar(50)', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'marital_status', + dataType: 'varchar(50)', + isNullable: true, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'children', + dataType: 'INTEGER', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: true, + comment: undefined, + }, + ], + }, + { + name: 'pet', + isView: false, + columns: [ + { + name: 'id', + dataType: 'INTEGER', + isNullable: true, + isAutoIncrementing: true, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'name', + dataType: 'varchar(255)', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'owner_id', + dataType: 'INTEGER', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'species', + dataType: 'varchar(50)', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + ], + }, + { + name: 'toy', + isView: false, + columns: [ + { + name: 'id', + dataType: 'INTEGER', + isNullable: true, + isAutoIncrementing: true, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'name', + dataType: 'varchar(255)', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'pet_id', + dataType: 'INTEGER', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + { + name: 'price', + dataType: 'double precision', + isNullable: false, + isAutoIncrementing: false, + hasDefaultValue: false, + comment: undefined, + }, + ], + }, + { + name: 'toy_names', + isView: true, + columns: [ + { + dataType: 'varchar(255)', + hasDefaultValue: false, + isAutoIncrementing: false, + isNullable: true, + name: 'name', + comment: undefined, + }, + ], + }, + ]) + } + }) }) async function createView() { @@ -522,7 +830,12 @@ for (const dialect of DIALECTS) { } else { await ctx.db.schema .createTable('some_schema.pet') - .addColumn('some_column', 'serial', (col) => col.primaryKey()) + .addColumn('some_column', 'integer', (col) => + col.identity().notNull().primaryKey() + ) + .addColumn('some_column_plus_1', sql``, (col) => + col.modifyEnd(sql`as (some_column + 1)`), + ) .execute() } } diff --git a/test/node/src/join.test.ts b/test/node/src/join.test.ts index 2a8c7496e..6031f7520 100644 --- a/test/node/src/join.test.ts +++ b/test/node/src/join.test.ts @@ -1,7 +1,6 @@ import { sql } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -10,6 +9,8 @@ import { testSql, expect, NOT_SUPPORTED, + DIALECTS, + limit, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -74,6 +75,10 @@ for (const dialect of DIALECTS) { sql: `select * from \`person\` inner join \`pet\` on \`pet\`.\`owner_id\` = \`person\`.\`id\` order by \`person\`.\`first_name\``, parameters: [], }, + mssql: { + sql: `select * from "person" inner join "pet" on "pet"."owner_id" = "person"."id" order by "person"."first_name"`, + parameters: [], + }, sqlite: { sql: `select * from "person" inner join "pet" on "pet"."owner_id" = "person"."id" order by "person"."first_name"`, parameters: [], @@ -111,7 +116,7 @@ for (const dialect of DIALECTS) { .select(['owner_id as oid', 'name']) .as('p'), 'p.oid', - 'person.id' + 'person.id', ) .selectAll() .orderBy('person.first_name') @@ -135,6 +140,15 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select * from "person"`, + `inner join (select "owner_id" as "oid", "name" from "pet") as "p"`, + `on "p"."oid" = "person"."id"`, + `order by "person"."first_name"`, + ], + parameters: [], + }, sqlite: { sql: [ `select * from "person"`, @@ -185,6 +199,10 @@ for (const dialect of DIALECTS) { sql: `select \`pet\`.\`name\` as \`pet_name\`, \`toy\`.\`name\` as \`toy_name\` from \`person\` inner join \`pet\` on \`pet\`.\`owner_id\` = \`person\`.\`id\` inner join \`toy\` on \`toy\`.\`pet_id\` = \`pet\`.\`id\` where \`first_name\` = ?`, parameters: ['Jennifer'], }, + mssql: { + sql: `select "pet"."name" as "pet_name", "toy"."name" as "toy_name" from "person" inner join "pet" on "pet"."owner_id" = "person"."id" inner join "toy" on "toy"."pet_id" = "pet"."id" where "first_name" = @1`, + parameters: ['Jennifer'], + }, sqlite: { sql: `select "pet"."name" as "pet_name", "toy"."name" as "toy_name" from "person" inner join "pet" on "pet"."owner_id" = "person"."id" inner join "toy" on "toy"."pet_id" = "pet"."id" where "first_name" = ?`, parameters: ['Jennifer'], @@ -209,20 +227,19 @@ for (const dialect of DIALECTS) { join .onRef('pet.owner_id', '=', 'person.id') .on('pet.name', 'in', ['Catto', 'Doggo', 'Hammo']) - .on(({ or, cmpr, ref, selectFrom }) => + .on(({ or, eb, ref, selectFrom }) => or([ - cmpr('pet.species', '=', 'cat'), - cmpr('species', '=', 'dog'), - cmpr( + eb('pet.species', '=', 'cat'), + eb('species', '=', 'dog'), + eb( ref('species'), '=', selectFrom('pet') .select(sql<'hamster'>`'hamster'`.as('hamster')) - .limit(1) - .offset(0) + .$call(limit(1, dialect)), ), - ]) - ) + ]), + ), ) .selectAll() .orderBy('person.first_name') @@ -234,10 +251,10 @@ for (const dialect of DIALECTS) { `inner join "pet"`, `on "pet"."owner_id" = "person"."id"`, `and "pet"."name" in ($1, $2, $3)`, - `and ("pet"."species" = $4 or "species" = $5 or "species" = (select 'hamster' as "hamster" from "pet" limit $6 offset $7))`, + `and ("pet"."species" = $4 or "species" = $5 or "species" = (select 'hamster' as "hamster" from "pet" limit $6))`, `order by "person"."first_name"`, ], - parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1, 0], + parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1], }, mysql: { sql: [ @@ -245,10 +262,21 @@ for (const dialect of DIALECTS) { 'inner join `pet`', 'on `pet`.`owner_id` = `person`.`id`', 'and `pet`.`name` in (?, ?, ?)', - "and (`pet`.`species` = ? or `species` = ? or `species` = (select 'hamster' as `hamster` from `pet` limit ? offset ?))", + "and (`pet`.`species` = ? or `species` = ? or `species` = (select 'hamster' as `hamster` from `pet` limit ?))", 'order by `person`.`first_name`', ], - parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1, 0], + parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1], + }, + mssql: { + sql: [ + `select * from "person"`, + `inner join "pet"`, + `on "pet"."owner_id" = "person"."id"`, + `and "pet"."name" in (@1, @2, @3)`, + `and ("pet"."species" = @4 or "species" = @5 or "species" = (select top(1) 'hamster' as "hamster" from "pet"))`, + `order by "person"."first_name"`, + ], + parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog'], }, sqlite: { sql: [ @@ -256,10 +284,10 @@ for (const dialect of DIALECTS) { `inner join "pet"`, `on "pet"."owner_id" = "person"."id"`, `and "pet"."name" in (?, ?, ?)`, - `and ("pet"."species" = ? or "species" = ? or "species" = (select 'hamster' as "hamster" from "pet" limit ? offset ?))`, + `and ("pet"."species" = ? or "species" = ? or "species" = (select 'hamster' as "hamster" from "pet" limit ?))`, `order by "person"."first_name"`, ], - parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1, 0], + parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1], }, }) @@ -273,18 +301,20 @@ for (const dialect of DIALECTS) { join .onRef('pet.owner_id', '=', 'person.id') .on('pet.name', 'in', ['Catto', 'Doggo', 'Hammo']) - .on((join) => - join - .on('pet.species', '=', 'cat') - .orOn('species', '=', 'dog') - .orOn(sql`${sql.ref('species')}`, '=', (qb) => - qb + .on((eb) => + eb.or([ + eb('pet.species', '=', 'cat'), + eb('species', '=', 'dog'), + eb( + eb.ref('species'), + '=', + eb .selectFrom('pet') - .select(sql`'hamster'`.as('hamster')) - .limit(1) - .offset(0) - ) - ) + .select(sql<'hamster'>`'hamster'`.as('hamster')) + .$call(limit(1, dialect)), + ), + ]), + ), ) .selectAll() .orderBy('person.first_name') @@ -296,10 +326,10 @@ for (const dialect of DIALECTS) { `inner join "pet"`, `on "pet"."owner_id" = "person"."id"`, `and "pet"."name" in ($1, $2, $3)`, - `and ("pet"."species" = $4 or "species" = $5 or "species" = (select 'hamster' as "hamster" from "pet" limit $6 offset $7))`, + `and ("pet"."species" = $4 or "species" = $5 or "species" = (select 'hamster' as "hamster" from "pet" limit $6))`, `order by "person"."first_name"`, ], - parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1, 0], + parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1], }, mysql: { sql: [ @@ -307,10 +337,21 @@ for (const dialect of DIALECTS) { 'inner join `pet`', 'on `pet`.`owner_id` = `person`.`id`', 'and `pet`.`name` in (?, ?, ?)', - "and (`pet`.`species` = ? or `species` = ? or `species` = (select 'hamster' as `hamster` from `pet` limit ? offset ?))", + "and (`pet`.`species` = ? or `species` = ? or `species` = (select 'hamster' as `hamster` from `pet` limit ?))", 'order by `person`.`first_name`', ], - parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1, 0], + parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1], + }, + mssql: { + sql: [ + `select * from "person"`, + `inner join "pet"`, + `on "pet"."owner_id" = "person"."id"`, + `and "pet"."name" in (@1, @2, @3)`, + `and ("pet"."species" = @4 or "species" = @5 or "species" = (select top(1) 'hamster' as "hamster" from "pet"))`, + `order by "person"."first_name"`, + ], + parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog'], }, sqlite: { sql: [ @@ -318,64 +359,68 @@ for (const dialect of DIALECTS) { `inner join "pet"`, `on "pet"."owner_id" = "person"."id"`, `and "pet"."name" in (?, ?, ?)`, - `and ("pet"."species" = ? or "species" = ? or "species" = (select 'hamster' as "hamster" from "pet" limit ? offset ?))`, + `and ("pet"."species" = ? or "species" = ? or "species" = (select 'hamster' as "hamster" from "pet" limit ?))`, `order by "person"."first_name"`, ], - parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1, 0], + parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1], }, }) await query.execute() }) - for (const [existsType, existsSql] of [ - ['onExists', 'exists'], - ['onNotExists', 'not exists'], - ] as const) { - it(`should inner joina table using "${existsType}" statements`, async () => { - const query = ctx.db - .selectFrom('person') - .innerJoin('pet', (join) => - join[existsType]((qb) => - qb - .selectFrom('pet as p') + it(`should inner join a table using "exists" statements`, async () => { + const query = ctx.db + .selectFrom('person') + .innerJoin('pet', (join) => + join.on(({ exists, selectFrom }) => + exists( + selectFrom('pet as p') .whereRef('p.id', '=', 'pet.id') .whereRef('p.owner_id', '=', 'person.id') - .select('id') - ) - ) - .select('pet.id') - - testSql(query, dialect, { - postgres: { - sql: [ - `select "pet"."id" from "person"`, - `inner join "pet" on ${existsSql}`, - `(select "id" from "pet" as "p" where "p"."id" = "pet"."id" and "p"."owner_id" = "person"."id")`, - ], - parameters: [], - }, - mysql: { - sql: [ - 'select `pet`.`id` from `person`', - `inner join \`pet\` on ${existsSql}`, - '(select `id` from `pet` as `p` where `p`.`id` = `pet`.`id` and `p`.`owner_id` = `person`.`id`)', - ], - parameters: [], - }, - sqlite: { - sql: [ - `select "pet"."id" from "person"`, - `inner join "pet" on ${existsSql}`, - `(select "id" from "pet" as "p" where "p"."id" = "pet"."id" and "p"."owner_id" = "person"."id")`, - ], - parameters: [], - }, - }) + .select('id'), + ), + ), + ) + .select('pet.id') - await query.execute() + testSql(query, dialect, { + postgres: { + sql: [ + `select "pet"."id" from "person"`, + `inner join "pet" on exists`, + `(select "id" from "pet" as "p" where "p"."id" = "pet"."id" and "p"."owner_id" = "person"."id")`, + ], + parameters: [], + }, + mysql: { + sql: [ + 'select `pet`.`id` from `person`', + `inner join \`pet\` on exists`, + '(select `id` from `pet` as `p` where `p`.`id` = `pet`.`id` and `p`.`owner_id` = `person`.`id`)', + ], + parameters: [], + }, + mssql: { + sql: [ + `select "pet"."id" from "person"`, + `inner join "pet" on exists`, + `(select "id" from "pet" as "p" where "p"."id" = "pet"."id" and "p"."owner_id" = "person"."id")`, + ], + parameters: [], + }, + sqlite: { + sql: [ + `select "pet"."id" from "person"`, + `inner join "pet" on exists`, + `(select "id" from "pet" as "p" where "p"."id" = "pet"."id" and "p"."owner_id" = "person"."id")`, + ], + parameters: [], + }, }) - } + + await query.execute() + }) }) describe('left join', () => { @@ -395,6 +440,10 @@ for (const dialect of DIALECTS) { sql: `select * from \`person\` left join \`pet\` on \`pet\`.\`owner_id\` = \`person\`.\`id\` order by \`person\`.\`first_name\``, parameters: [], }, + mssql: { + sql: `select * from "person" left join "pet" on "pet"."owner_id" = "person"."id" order by "person"."first_name"`, + parameters: [], + }, sqlite: { sql: `select * from "person" left join "pet" on "pet"."owner_id" = "person"."id" order by "person"."first_name"`, parameters: [], @@ -413,7 +462,7 @@ for (const dialect of DIALECTS) { .select(['owner_id as oid', 'name']) .as('p'), 'p.oid', - 'person.id' + 'person.id', ) .selectAll() .orderBy('person.first_name') @@ -437,6 +486,15 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + `select * from "person"`, + `left join (select "owner_id" as "oid", "name" from "pet") as "p"`, + `on "p"."oid" = "person"."id"`, + `order by "person"."first_name"`, + ], + parameters: [], + }, sqlite: { sql: [ `select * from "person"`, @@ -468,6 +526,10 @@ for (const dialect of DIALECTS) { sql: `select \`pet\`.\`name\` as \`pet_name\`, \`toy\`.\`name\` as \`toy_name\` from \`person\` left join \`pet\` on \`pet\`.\`owner_id\` = \`person\`.\`id\` left join \`toy\` on \`toy\`.\`pet_id\` = \`pet\`.\`id\` where \`first_name\` = ?`, parameters: ['Jennifer'], }, + mssql: { + sql: `select "pet"."name" as "pet_name", "toy"."name" as "toy_name" from "person" left join "pet" on "pet"."owner_id" = "person"."id" left join "toy" on "toy"."pet_id" = "pet"."id" where "first_name" = @1`, + parameters: ['Jennifer'], + }, sqlite: { sql: `select "pet"."name" as "pet_name", "toy"."name" as "toy_name" from "person" left join "pet" on "pet"."owner_id" = "person"."id" left join "toy" on "toy"."pet_id" = "pet"."id" where "first_name" = ?`, parameters: ['Jennifer'], @@ -484,18 +546,20 @@ for (const dialect of DIALECTS) { join .onRef('pet.owner_id', '=', 'person.id') .on('pet.name', 'in', ['Catto', 'Doggo', 'Hammo']) - .on((join) => - join - .on('pet.species', '=', 'cat') - .orOn('species', '=', 'dog') - .orOn(sql`${sql.ref('species')}`, '=', (qb) => - qb + .on(({ or, eb }) => + or([ + eb('pet.species', '=', 'cat'), + eb('species', '=', 'dog'), + eb( + sql`${sql.ref('species')}`, + '=', + eb .selectFrom('pet') .select(sql`'hamster'`.as('hamster')) - .limit(1) - .offset(0) - ) - ) + .$call(limit(1, dialect)), + ), + ]), + ), ) .selectAll() .orderBy('person.first_name') @@ -507,10 +571,10 @@ for (const dialect of DIALECTS) { `left join "pet"`, `on "pet"."owner_id" = "person"."id"`, `and "pet"."name" in ($1, $2, $3)`, - `and ("pet"."species" = $4 or "species" = $5 or "species" = (select 'hamster' as "hamster" from "pet" limit $6 offset $7))`, + `and ("pet"."species" = $4 or "species" = $5 or "species" = (select 'hamster' as "hamster" from "pet" limit $6))`, `order by "person"."first_name"`, ], - parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1, 0], + parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1], }, mysql: { sql: [ @@ -518,10 +582,21 @@ for (const dialect of DIALECTS) { 'left join `pet`', 'on `pet`.`owner_id` = `person`.`id`', 'and `pet`.`name` in (?, ?, ?)', - "and (`pet`.`species` = ? or `species` = ? or `species` = (select 'hamster' as `hamster` from `pet` limit ? offset ?))", + "and (`pet`.`species` = ? or `species` = ? or `species` = (select 'hamster' as `hamster` from `pet` limit ?))", 'order by `person`.`first_name`', ], - parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1, 0], + parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1], + }, + mssql: { + sql: [ + `select * from "person"`, + `left join "pet"`, + `on "pet"."owner_id" = "person"."id"`, + `and "pet"."name" in (@1, @2, @3)`, + `and ("pet"."species" = @4 or "species" = @5 or "species" = (select top(1) 'hamster' as "hamster" from "pet"))`, + `order by "person"."first_name"`, + ], + parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog'], }, sqlite: { sql: [ @@ -529,67 +604,57 @@ for (const dialect of DIALECTS) { `left join "pet"`, `on "pet"."owner_id" = "person"."id"`, `and "pet"."name" in (?, ?, ?)`, - `and ("pet"."species" = ? or "species" = ? or "species" = (select 'hamster' as "hamster" from "pet" limit ? offset ?))`, + `and ("pet"."species" = ? or "species" = ? or "species" = (select 'hamster' as "hamster" from "pet" limit ?))`, `order by "person"."first_name"`, ], - parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1, 0], + parameters: ['Catto', 'Doggo', 'Hammo', 'cat', 'dog', 1], }, }) await query.execute() }) - for (const [existsType, existsSql] of [ - ['onExists', 'exists'], - ['onNotExists', 'not exists'], - ] as const) { - it(`should left joina table using "${existsType}" statements`, async () => { - const query = ctx.db - .selectFrom('person') - .leftJoin('pet', (join) => - join[existsType]((qb) => - qb - .selectFrom('pet as p') - .whereRef('p.id', '=', 'pet.id') - .whereRef('p.owner_id', '=', 'person.id') - .select('id') - ) - ) - .select('pet.id') - - testSql(query, dialect, { - postgres: { - sql: [ - `select "pet"."id" from "person"`, - `left join "pet" on ${existsSql}`, - `(select "id" from "pet" as "p" where "p"."id" = "pet"."id" and "p"."owner_id" = "person"."id")`, - ], - parameters: [], - }, - mysql: { - sql: [ - 'select `pet`.`id` from `person`', - `left join \`pet\` on ${existsSql}`, - '(select `id` from `pet` as `p` where `p`.`id` = `pet`.`id` and `p`.`owner_id` = `person`.`id`)', - ], - parameters: [], - }, - sqlite: { - sql: [ - `select "pet"."id" from "person"`, - `left join "pet" on ${existsSql}`, - `(select "id" from "pet" as "p" where "p"."id" = "pet"."id" and "p"."owner_id" = "person"."id")`, - ], - parameters: [], - }, - }) + it(`should left join a table using "not exists" statements`, async () => { + const query = ctx.db + .selectFrom('person') + .leftJoin('pet', (join) => + join.on(({ not, exists, selectFrom }) => + not( + exists( + selectFrom('pet as p') + .whereRef('p.id', '=', 'pet.id') + .whereRef('p.owner_id', '=', 'person.id') + .select('id'), + ), + ), + ), + ) + .select('pet.id') - await query.execute() + testSql(query, dialect, { + postgres: { + sql: `select "pet"."id" from "person" left join "pet" on not exists (select "id" from "pet" as "p" where "p"."id" = "pet"."id" and "p"."owner_id" = "person"."id")`, + parameters: [], + }, + mysql: { + sql: 'select `pet`.`id` from `person` left join `pet` on not exists (select `id` from `pet` as `p` where `p`.`id` = `pet`.`id` and `p`.`owner_id` = `person`.`id`)', + parameters: [], + }, + mssql: { + sql: `select "pet"."id" from "person" left join "pet" on not exists (select "id" from "pet" as "p" where "p"."id" = "pet"."id" and "p"."owner_id" = "person"."id")`, + parameters: [], + }, + sqlite: { + sql: `select "pet"."id" from "person" left join "pet" on not exists (select "id" from "pet" as "p" where "p"."id" = "pet"."id" and "p"."owner_id" = "person"."id")`, + parameters: [], + }, }) - } + + await query.execute() + }) }) - if (dialect !== 'sqlite') { + if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'mssql') { describe('right join', () => { it(`should right join a table`, async () => { const query = ctx.db @@ -607,10 +672,11 @@ for (const dialect of DIALECTS) { sql: `select * from \`person\` right join \`pet\` on \`pet\`.\`owner_id\` = \`person\`.\`id\` order by \`person\`.\`first_name\``, parameters: [], }, - sqlite: { + mssql: { sql: `select * from "person" right join "pet" on "pet"."owner_id" = "person"."id" order by "person"."first_name"`, parameters: [], }, + sqlite: NOT_SUPPORTED, }) await query.execute() @@ -618,7 +684,7 @@ for (const dialect of DIALECTS) { }) } - if (dialect === 'postgres') { + if (dialect === 'postgres' || dialect === 'mssql') { describe('full join', () => { it(`should full join a table`, async () => { const query = ctx.db @@ -633,13 +699,19 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: `select * from "person" full join "pet" on "pet"."owner_id" = "person"."id" order by "person"."first_name"`, + parameters: [], + }, sqlite: NOT_SUPPORTED, }) await query.execute() }) }) + } + if (dialect === 'postgres') { describe('lateral join', () => { it('should join an expression laterally', async () => { const query = ctx.db @@ -651,7 +723,7 @@ for (const dialect of DIALECTS) { .select('name') .whereRef('pet.owner_id', '=', 'person.id') .as('p'), - (join) => join.onTrue() + (join) => join.onTrue(), ) .select(['first_name', 'p.name']) .orderBy('first_name') @@ -662,6 +734,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -683,7 +756,7 @@ for (const dialect of DIALECTS) { .select('name') .whereRef('pet.owner_id', '=', 'person.id') .as('p'), - (join) => join.onTrue() + (join) => join.onTrue(), ) .select(['first_name', 'p.name']) .orderBy('first_name') @@ -694,6 +767,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) diff --git a/test/node/src/json-traversal.test.ts b/test/node/src/json-traversal.test.ts new file mode 100644 index 000000000..363aeb33e --- /dev/null +++ b/test/node/src/json-traversal.test.ts @@ -0,0 +1,845 @@ +import { + ColumnDefinitionBuilder, + JSONColumnType, + ParseJSONResultsPlugin, + SqlBool, + sql, +} from '../../..' +import { + BuiltInDialect, + DIALECTS, + NOT_SUPPORTED, + clearDatabase, + destroyTest, + expect, + initTest, + insertDefaultDataSet, + testSql, +} from './test-setup.js' + +type TestContext = Awaited> + +for (const dialect of DIALECTS.filter((dialect) => dialect !== 'mssql')) { + describe(`${dialect}: json traversal`, () => { + let ctx: TestContext + + before(async function () { + ctx = await initJSONTest(this, dialect) + }) + + beforeEach(async () => { + await insertDefaultJSONDataSet(ctx) + }) + + afterEach(async () => { + await clearJSONDatabase(ctx) + }) + + after(async () => { + await destroyJSONTest(ctx) + }) + + if (dialect === 'mysql' || dialect === 'sqlite') { + describe('JSON reference using JSON Path syntax ($)', () => { + const jsonOperator = dialect === 'mysql' ? '->$' : '->>$' + + it(`should execute a query with column${jsonOperator}.key in select clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb.ref('website', jsonOperator).key('url').as('website_url'), + ) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: { + parameters: [], + sql: "select `website`->'$.url' as `website_url` from `person_metadata`", + }, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select "website"->>'$.url' as "website_url" from "person_metadata"`, + }, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { website_url: 'https://www.jenniferaniston.com' }, + { website_url: 'https://www.arnoldschwarzenegger.com' }, + { website_url: 'https://www.sylvesterstallone.com' }, + ]) + }) + + it(`should execute a query with column${jsonOperator}[0] in select clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb.ref('nicknames', jsonOperator).at(0).as('nickname'), + ) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: { + parameters: [], + sql: "select `nicknames`->'$[0]' as `nickname` from `person_metadata`", + }, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select "nicknames"->>'$[0]' as "nickname" from "person_metadata"`, + }, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { nickname: 'J.A.' }, + { nickname: 'A.S.' }, + { nickname: 'S.S.' }, + ]) + }) + + it(`should execute a query with column${jsonOperator}.key.key in select clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb + .ref('profile', jsonOperator) + .key('auth') + .key('roles') + .as('roles'), + ) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: { + parameters: [], + sql: "select `profile`->'$.auth.roles' as `roles` from `person_metadata`", + }, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select "profile"->>'$.auth.roles' as "roles" from "person_metadata"`, + }, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { roles: ['contributor', 'moderator'] }, + { roles: ['contributor', 'moderator'] }, + { roles: ['contributor', 'moderator'] }, + ]) + }) + + it(`should execute a query with column${jsonOperator}.key[0] in select clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb.ref('profile', jsonOperator).key('tags').at(0).as('main_tag'), + ) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: { + parameters: [], + sql: "select `profile`->'$.tags[0]' as `main_tag` from `person_metadata`", + }, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select "profile"->>'$.tags[0]' as "main_tag" from "person_metadata"`, + }, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { main_tag: 'awesome' }, + { main_tag: 'awesome' }, + { main_tag: 'awesome' }, + ]) + }) + + it(`should execute a query with column${jsonOperator}[0].key in select clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb + .ref('experience', jsonOperator) + .at(0) + .key('establishment') + .as('establishment'), + ) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: { + parameters: [], + sql: "select `experience`->'$[0].establishment' as `establishment` from `person_metadata`", + }, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select "experience"->>'$[0].establishment' as "establishment" from "person_metadata"`, + }, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { establishment: 'The University of Life' }, + { establishment: 'The University of Life' }, + { establishment: 'The University of Life' }, + ]) + }) + + it(`should execute a query with column${jsonOperator}[0][0] in select clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb + .ref('schedule', jsonOperator) + .at(0) + .at(0) + .as('january_1st_schedule'), + ) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: { + parameters: [], + sql: "select `schedule`->'$[0][0]' as `january_1st_schedule` from `person_metadata`", + }, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select "schedule"->>'$[0][0]' as "january_1st_schedule" from "person_metadata"`, + }, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { january_1st_schedule: [{ name: 'Gym', time: '12:15' }] }, + { january_1st_schedule: [{ name: 'Gym', time: '12:15' }] }, + { january_1st_schedule: [{ name: 'Gym', time: '12:15' }] }, + ]) + }) + + if (dialect === 'mysql') { + it('should execute a query with column->$[last] in select clause', async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb.ref('nicknames', '->$').at('last').as('nickname'), + ) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: { + parameters: [], + sql: "select `nicknames`->'$[last]' as `nickname` from `person_metadata`", + }, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { nickname: 'Aniston the Magnificent' }, + { nickname: 'Schwarzenegger the Magnificent' }, + { nickname: 'Stallone the Magnificent' }, + ]) + }) + } + + if (dialect === 'sqlite') { + it('should execute a query with column->>$[#-1] in select clause', async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb.ref('nicknames', '->>$').at('#-1').as('nickname'), + ) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select "nicknames"->>'$[#-1]' as "nickname" from "person_metadata"`, + }, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { nickname: 'Aniston the Magnificent' }, + { nickname: 'Schwarzenegger the Magnificent' }, + { nickname: 'Stallone the Magnificent' }, + ]) + }) + } + + const expectedBooleanValue = dialect === 'mysql' ? true : 1 + + it(`should execute a query with column${jsonOperator} in select clause with non-string properties`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => [ + eb + .ref('profile', jsonOperator) + .key('auth') + .key('is_verified') + .as('is_verified'), + eb + .ref('profile', jsonOperator) + .key('auth') + .key('login_count') + .as('login_count'), + eb.ref('profile', jsonOperator).key('avatar').as('avatar'), + ]) + + const results = await query.execute() + + expect(results).to.containSubset([ + { + is_verified: expectedBooleanValue, + login_count: 12, + avatar: null, + }, + ]) + }) + + it(`should execute a query with column${jsonOperator}.key.key in where clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .where((eb) => + eb( + eb.ref('profile', jsonOperator).key('auth').key('login_count'), + '=', + 12, + ), + ) + .selectAll() + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: { + parameters: [12], + sql: "select * from `person_metadata` where `profile`->'$.auth.login_count' = ?", + }, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [12], + sql: `select * from "person_metadata" where "profile"->>'$.auth.login_count' = ?`, + }, + }) + + const results = await query.execute() + + expect(results).to.have.length(1) + expect(results[0].profile.auth.login_count).to.equal(12) + }) + + it(`should execute a query with column${jsonOperator}.key.key in order by clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .orderBy( + (eb) => + eb.ref('profile', jsonOperator).key('auth').key('login_count'), + 'desc', + ) + .selectAll() + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: { + parameters: [], + sql: "select * from `person_metadata` order by `profile`->'$.auth.login_count' desc", + }, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select * from "person_metadata" order by "profile"->>'$.auth.login_count' desc`, + }, + }) + + const results = await query.execute() + + expect(results).to.have.length(3) + expect(results[0].profile.auth.login_count).to.equal(14) + expect(results[1].profile.auth.login_count).to.equal(13) + expect(results[2].profile.auth.login_count).to.equal(12) + }) + }) + + describe('Standalone JSON path syntax ($)', () => { + it('should execute a query with json_set function', async () => { + const lastItem = dialect === 'mysql' ? 'last' : '#-1' + + const query = ctx.db + .updateTable('person_metadata') + .set('experience', (eb) => + eb.fn('json_set', [ + 'experience', + eb.jsonPath<'experience'>().at(lastItem).key('establishment'), + eb.val('Papa Johns'), + ]), + ) + .where('person_id', '=', 911) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: { + parameters: ['Papa Johns', 911], + sql: "update `person_metadata` set `experience` = json_set(`experience`, '$[last].establishment', ?) where `person_id` = ?", + }, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: ['Papa Johns', 911], + sql: `update "person_metadata" set "experience" = json_set("experience", '$[#-1].establishment', ?) where "person_id" = ?`, + }, + }) + + await query.execute() + }) + }) + } + + if (dialect === 'postgres' || dialect === 'sqlite') { + describe('JSON reference using PostgreSQL-style syntax (->->->>)', () => { + const jsonOperator = dialect === 'postgres' ? '->' : '->>' + + it(`should execute a query with column${jsonOperator}key in select clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb.ref('website', jsonOperator).key('url').as('website_url'), + ) + + testSql(query, dialect, { + postgres: { + parameters: [], + sql: `select "website"->'url' as "website_url" from "person_metadata"`, + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select "website"->>'url' as "website_url" from "person_metadata"`, + }, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { website_url: 'https://www.jenniferaniston.com' }, + { website_url: 'https://www.arnoldschwarzenegger.com' }, + { website_url: 'https://www.sylvesterstallone.com' }, + ]) + }) + + it(`should execute a query with column${jsonOperator}0 in select clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb.ref('nicknames', jsonOperator).at(0).as('nickname'), + ) + + testSql(query, dialect, { + postgres: { + parameters: [], + sql: `select "nicknames"->0 as "nickname" from "person_metadata"`, + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select "nicknames"->>0 as "nickname" from "person_metadata"`, + }, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { nickname: 'J.A.' }, + { nickname: 'A.S.' }, + { nickname: 'S.S.' }, + ]) + }) + + it(`should execute a query with column->key${jsonOperator}key in select clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb + .ref('profile', jsonOperator) + .key('auth') + .key('roles') + .as('roles'), + ) + + testSql(query, dialect, { + postgres: { + parameters: [], + sql: `select "profile"->'auth'->'roles' as "roles" from "person_metadata"`, + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select "profile"->'auth'->>'roles' as "roles" from "person_metadata"`, + }, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { roles: ['contributor', 'moderator'] }, + { roles: ['contributor', 'moderator'] }, + { roles: ['contributor', 'moderator'] }, + ]) + }) + + it(`should execute a query with column->key${jsonOperator}0 in select clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb.ref('profile', jsonOperator).key('tags').at(0).as('main_tag'), + ) + + testSql(query, dialect, { + postgres: { + parameters: [], + sql: `select "profile"->'tags'->0 as "main_tag" from "person_metadata"`, + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select "profile"->'tags'->>0 as "main_tag" from "person_metadata"`, + }, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { main_tag: 'awesome' }, + { main_tag: 'awesome' }, + { main_tag: 'awesome' }, + ]) + }) + + it(`should execute a query with column->0${jsonOperator}key in select clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb + .ref('experience', jsonOperator) + .at(0) + .key('establishment') + .as('establishment'), + ) + + testSql(query, dialect, { + postgres: { + parameters: [], + sql: `select "experience"->0->'establishment' as "establishment" from "person_metadata"`, + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select "experience"->0->>'establishment' as "establishment" from "person_metadata"`, + }, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { establishment: 'The University of Life' }, + { establishment: 'The University of Life' }, + { establishment: 'The University of Life' }, + ]) + }) + + it(`should execute a query with column->0${jsonOperator}0 in select clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => + eb + .ref('schedule', jsonOperator) + .at(0) + .at(0) + .as('january_1st_schedule'), + ) + + testSql(query, dialect, { + postgres: { + parameters: [], + sql: `select "schedule"->0->0 as "january_1st_schedule" from "person_metadata"`, + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select "schedule"->0->>0 as "january_1st_schedule" from "person_metadata"`, + }, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { january_1st_schedule: [{ name: 'Gym', time: '12:15' }] }, + { january_1st_schedule: [{ name: 'Gym', time: '12:15' }] }, + { january_1st_schedule: [{ name: 'Gym', time: '12:15' }] }, + ]) + }) + + if (dialect === 'postgres') { + it('should execute a query with column->-1 in select clause', async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => eb.ref('nicknames', '->').at(-1).as('nickname')) + + testSql(query, dialect, { + postgres: { + parameters: [], + sql: `select "nicknames"->-1 as "nickname" from "person_metadata"`, + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + const results = await query.execute() + + expect(results).to.containSubset([ + { nickname: 'Aniston the Magnificent' }, + { nickname: 'Schwarzenegger the Magnificent' }, + { nickname: 'Stallone the Magnificent' }, + ]) + }) + } + + const expectedBooleanValue = dialect === 'postgres' ? true : 1 + + it(`should execute a query with column${jsonOperator} in select clause with non-string properties`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .select((eb) => [ + eb + .ref('profile', jsonOperator) + .key('auth') + .key('is_verified') + .as('is_verified'), + eb + .ref('profile', jsonOperator) + .key('auth') + .key('login_count') + .as('login_count'), + eb.ref('profile', jsonOperator).key('avatar').as('avatar'), + ]) + + const results = await query.execute() + + expect(results).to.containSubset([ + { + is_verified: expectedBooleanValue, + login_count: 12, + avatar: null, + }, + ]) + }) + + it(`should execute a query with column->key${jsonOperator}key in where clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .where((eb) => + eb( + eb.ref('profile', jsonOperator).key('auth').key('login_count'), + '=', + 12, + ), + ) + .selectAll() + + testSql(query, dialect, { + postgres: { + parameters: [12], + sql: `select * from "person_metadata" where "profile"->'auth'->'login_count' = $1`, + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [12], + sql: `select * from "person_metadata" where "profile"->'auth'->>'login_count' = ?`, + }, + }) + + const results = await query.execute() + + expect(results).to.have.length(1) + expect(results[0].profile.auth.login_count).to.equal(12) + }) + + it(`should execute a query with column->key${jsonOperator}key in order by clause`, async () => { + const query = ctx.db + .selectFrom('person_metadata') + .orderBy( + (eb) => + eb.ref('profile', jsonOperator).key('auth').key('login_count'), + 'desc', + ) + .selectAll() + + testSql(query, dialect, { + postgres: { + parameters: [], + sql: `select * from "person_metadata" order by "profile"->'auth'->'login_count' desc`, + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: { + parameters: [], + sql: `select * from "person_metadata" order by "profile"->'auth'->>'login_count' desc`, + }, + }) + + const results = await query.execute() + + expect(results).to.have.length(3) + expect(results[0].profile.auth.login_count).to.equal(14) + expect(results[1].profile.auth.login_count).to.equal(13) + expect(results[2].profile.auth.login_count).to.equal(12) + }) + }) + } + }) +} + +async function initJSONTest( + ctx: Mocha.Context, + dialect: D, +) { + const testContext = await initTest(ctx, dialect) + + let db = testContext.db.withTables<{ + person_metadata: { + person_id: number + website: JSONColumnType<{ url: string }> + nicknames: JSONColumnType + profile: JSONColumnType<{ + auth: { + roles: string[] + last_login?: { device: string } + is_verified: SqlBool + login_count: number + } + avatar: string | null + tags: string[] + }> + experience: JSONColumnType< + { + establishment: string + }[] + > + schedule: JSONColumnType<{ name: string; time: string }[][][]> + } + }>() + + if (dialect === 'sqlite') { + db = db.withPlugin(new ParseJSONResultsPlugin()) + } + + const jsonColumnDataType = resolveJSONColumnDataType(dialect) + const notNull = (cb: ColumnDefinitionBuilder) => cb.notNull() + + await db.schema + .createTable('person_metadata') + .addColumn('person_id', 'integer', (cb) => + cb.primaryKey().references('person.id'), + ) + .addColumn('website', jsonColumnDataType, notNull) + .addColumn('nicknames', jsonColumnDataType, notNull) + .addColumn('profile', jsonColumnDataType, notNull) + .addColumn('experience', jsonColumnDataType, notNull) + .addColumn('schedule', jsonColumnDataType, notNull) + .execute() + + return { ...testContext, db } +} + +function resolveJSONColumnDataType(dialect: BuiltInDialect) { + switch (dialect) { + case 'postgres': + return 'jsonb' + case 'mysql': + return 'json' + case 'mssql': + return sql`nvarchar(max)` + case 'sqlite': + return 'text' + } +} + +async function insertDefaultJSONDataSet(ctx: TestContext) { + await insertDefaultDataSet(ctx as any) + + const people = await ctx.db + .selectFrom('person') + .select(['id', 'first_name', 'last_name']) + .execute() + + await ctx.db + .insertInto('person_metadata') + .values( + people + .filter((person) => person.first_name && person.last_name) + .map((person, index) => ({ + person_id: person.id, + website: JSON.stringify({ + url: `https://www.${person.first_name!.toLowerCase()}${person.last_name!.toLowerCase()}.com`, + }), + nicknames: JSON.stringify([ + `${person.first_name![0]}.${person.last_name![0]}.`, + `${person.first_name} the Great`, + `${person.last_name} the Magnificent`, + ]), + profile: JSON.stringify({ + tags: ['awesome'], + auth: { + roles: ['contributor', 'moderator'], + last_login: { + device: 'android', + }, + login_count: 12 + index, + is_verified: true, + }, + avatar: null, + }), + experience: JSON.stringify([ + { + establishment: 'The University of Life', + }, + ]), + schedule: JSON.stringify([[[{ name: 'Gym', time: '12:15' }]]]), + })), + ) + .execute() +} + +async function clearJSONDatabase(ctx: TestContext) { + await ctx.db.deleteFrom('person_metadata').execute() + await clearDatabase(ctx as any) +} + +async function destroyJSONTest(ctx: TestContext) { + await ctx.db.schema.dropTable('person_metadata').execute() + await destroyTest(ctx as any) +} diff --git a/test/node/src/json.test.ts b/test/node/src/json.test.ts index 848f22409..5a275da7d 100644 --- a/test/node/src/json.test.ts +++ b/test/node/src/json.test.ts @@ -1,4 +1,10 @@ -import { Generated, Kysely, RawBuilder, sql } from '../../..' +import { + Generated, + Kysely, + RawBuilder, + sql, + ParseJSONResultsPlugin, +} from '../../..' import { jsonArrayFrom as pg_jsonArrayFrom, jsonObjectFrom as pg_jsonObjectFrom, @@ -9,6 +15,16 @@ import { jsonObjectFrom as mysql_jsonObjectFrom, jsonBuildObject as mysql_jsonBuildObject, } from '../../../helpers/mysql' +import { + jsonArrayFrom as mssql_jsonArrayFrom, + jsonObjectFrom as mssql_jsonObjectFrom, + jsonBuildObject as mssql_jsonBuildObject, +} from '../../../helpers/mssql' +import { + jsonArrayFrom as sqlite_jsonArrayFrom, + jsonObjectFrom as sqlite_jsonObjectFrom, + jsonBuildObject as sqlite_jsonBuildObject, +} from '../../../helpers/sqlite' import { destroyTest, @@ -19,6 +35,8 @@ import { insertDefaultDataSet, clearDatabase, DIALECTS, + orderBy, + limit, } from './test-setup.js' interface JsonTable { @@ -31,19 +49,32 @@ interface JsonTable { } } -for (const dialect of DIALECTS) { - if (dialect !== 'postgres' && dialect !== 'mysql') { - continue - } - - const jsonArrayFrom = - dialect === 'postgres' ? pg_jsonArrayFrom : mysql_jsonArrayFrom - - const jsonObjectFrom = - dialect === 'postgres' ? pg_jsonObjectFrom : mysql_jsonObjectFrom +const jsonFunctions = { + postgres: { + jsonArrayFrom: pg_jsonArrayFrom, + jsonObjectFrom: pg_jsonObjectFrom, + jsonBuildObject: pg_jsonBuildObject, + }, + mysql: { + jsonArrayFrom: mysql_jsonArrayFrom, + jsonObjectFrom: mysql_jsonObjectFrom, + jsonBuildObject: mysql_jsonBuildObject, + }, + mssql: { + jsonArrayFrom: mssql_jsonArrayFrom, + jsonObjectFrom: mssql_jsonObjectFrom, + jsonBuildObject: mssql_jsonBuildObject, + }, + sqlite: { + jsonArrayFrom: sqlite_jsonArrayFrom, + jsonObjectFrom: sqlite_jsonObjectFrom, + jsonBuildObject: sqlite_jsonBuildObject, + }, +} as const - const jsonBuildObject = - dialect === 'postgres' ? pg_jsonBuildObject : mysql_jsonBuildObject +for (const dialect of DIALECTS) { + const { jsonArrayFrom, jsonObjectFrom, jsonBuildObject } = + jsonFunctions[dialect] describe(`${dialect} json tests`, () => { let ctx: TestContext @@ -59,6 +90,10 @@ for (const dialect of DIALECTS) { .addColumn('id', 'serial', (col) => col.primaryKey()) .addColumn('data', 'jsonb') .execute() + } else if (dialect === 'mssql') { + await sql`if object_id(N'json_table', N'U') is null begin create table json_table (id int primary key identity, data nvarchar(1024)); end;`.execute( + ctx.db, + ) } else { await ctx.db.schema .createTable('json_table') @@ -69,6 +104,10 @@ for (const dialect of DIALECTS) { } db = ctx.db.withTables<{ json_table: JsonTable }>() + + if (dialect === 'mssql' || dialect === 'sqlite') { + db = db.withPlugin(new ParseJSONResultsPlugin()) + } }) beforeEach(async () => { @@ -119,7 +158,196 @@ for (const dialect of DIALECTS) { expect(result.numInsertedOrUpdatedRows).to.equal(1n) }) - it('should select subqueries as nested jsonb objects', async () => { + if (dialect === 'postgres') { + it('should update json data of a row using the subscript syntax and a raw sql snippet', async () => { + await db + .insertInto('json_table') + .values({ + data: toJson({ + number_field: 1, + nested: { string_field: 'a' }, + }), + }) + .executeTakeFirstOrThrow() + + const newValue = Math.random() + await db + .updateTable('json_table') + .set(sql`data['number_field']`, newValue) + .executeTakeFirstOrThrow() + + const result = await db + .selectFrom('json_table') + .select('data') + .executeTakeFirstOrThrow() + + expect(result.data.number_field).to.equal(newValue) + }) + } + + if (dialect === 'postgres') { + it('should aggregate a joined table using json_agg', async () => { + const res = 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() + + expect(res).to.have.length(3) + expect(res).to.containSubset([ + { + first_name: 'Jennifer', + pets: [{ name: 'Catto', species: 'cat' }], + }, + { + first_name: 'Arnold', + pets: [ + { + name: 'Doggo', + species: 'dog', + }, + ], + }, + { + first_name: 'Sylvester', + pets: [{ name: 'Hammo', species: 'hamster' }], + }, + ]) + }) + + it('should aggregate a joined table using json_agg and distinct', async () => { + const res = await db + .selectFrom('person') + .innerJoin('pet', 'pet.owner_id', 'person.id') + .select((eb) => [ + 'first_name', + eb.fn.jsonAgg('pet').distinct().as('pets'), + ]) + .groupBy('person.first_name') + .execute() + + expect(res).to.have.length(3) + expect(res).to.containSubset([ + { + first_name: 'Jennifer', + pets: [{ name: 'Catto', species: 'cat' }], + }, + { + first_name: 'Arnold', + pets: [ + { + name: 'Doggo', + species: 'dog', + }, + ], + }, + { + first_name: 'Sylvester', + pets: [{ name: 'Hammo', species: 'hamster' }], + }, + ]) + }) + + it('should aggregate a subquery using json_agg', async () => { + const res = await db + .selectFrom('person') + .select((eb) => [ + 'first_name', + eb + .selectFrom('pet') + .select((eb) => eb.fn.jsonAgg('pet').as('pet')) + .whereRef('pet.owner_id', '=', 'person.id') + .as('pets'), + ]) + .execute() + + expect(res).to.have.length(3) + expect(res).to.containSubset([ + { + first_name: 'Jennifer', + pets: [{ name: 'Catto', species: 'cat' }], + }, + { + first_name: 'Arnold', + pets: [ + { + name: 'Doggo', + species: 'dog', + }, + ], + }, + { + first_name: 'Sylvester', + pets: [{ name: 'Hammo', species: 'hamster' }], + }, + ]) + }) + + it('should aggregate a subquery using json_agg and eb.table', async () => { + const res = await db + .selectFrom('person') + .select((eb) => [ + 'first_name', + eb + .selectFrom('pet') + .select((eb) => eb.fn.jsonAgg(eb.table('pet')).as('pet')) + .whereRef('pet.owner_id', '=', 'person.id') + .as('pets'), + ]) + .execute() + + expect(res).to.have.length(3) + expect(res).to.containSubset([ + { + first_name: 'Jennifer', + pets: [{ name: 'Catto', species: 'cat' }], + }, + { + first_name: 'Arnold', + pets: [ + { + name: 'Doggo', + species: 'dog', + }, + ], + }, + { + first_name: 'Sylvester', + pets: [{ name: 'Hammo', species: 'hamster' }], + }, + ]) + }) + + it('should jsonify a joined table using to_json', async () => { + const res = await db + .selectFrom('person') + .innerJoin('pet', 'pet.owner_id', 'person.id') + .select((eb) => ['first_name', eb.fn.toJson('pet').as('pet')]) + .execute() + + expect(res).to.have.length(3) + expect(res).to.containSubset([ + { + first_name: 'Jennifer', + pet: { name: 'Catto', species: 'cat' }, + }, + { + first_name: 'Arnold', + pet: { + name: 'Doggo', + species: 'dog', + }, + }, + { + first_name: 'Sylvester', + pet: { name: 'Hammo', species: 'hamster' }, + }, + ]) + }) + } + + it('should select subqueries as nested json objects', async () => { const query = db.selectFrom('person').select((eb) => [ 'person.first_name', @@ -137,11 +365,11 @@ for (const dialect of DIALECTS) { .selectFrom('toy') .select('toy.name') .whereRef('toy.pet_id', '=', 'pet.id') - .orderBy('toy.name', 'asc') + .$call(orderBy('toy.name', 'asc', dialect)), ).as('toys'), ]) .whereRef('owner_id', '=', 'person.id') - .orderBy('pet.name') + .$call(orderBy('pet.name', 'asc', dialect)), ).as('pets'), // Nest the first found dog the person owns @@ -151,15 +379,18 @@ for (const dialect of DIALECTS) { .select('name as doggo_name') .whereRef('owner_id', '=', 'person.id') .where('species', '=', 'dog') - .orderBy('name') - .limit(1) + .orderBy('name', 'asc') + .$call(limit(1, dialect)), ).as('doggo'), // Nest an object that holds the person's formatted name jsonBuildObject({ first: eb.ref('first_name'), last: eb.ref('last_name'), - full: eb.fn('concat', ['first_name', sql.lit(' '), 'last_name']), + full: + dialect === 'sqlite' + ? sql`first_name || ' ' || last_name` + : eb.fn('concat', ['first_name', sql.lit(' '), 'last_name']), }).as('name'), // Nest an empty list @@ -167,7 +398,7 @@ for (const dialect of DIALECTS) { eb .selectFrom('pet') .select('id') - .where((eb) => eb.val(false)) + .where(sql`1 = 2`), ).as('emptyList'), ]) diff --git a/test/node/src/log-once.test.ts b/test/node/src/log-once.test.ts index e2d7c61c7..76e7d9508 100644 --- a/test/node/src/log-once.test.ts +++ b/test/node/src/log-once.test.ts @@ -7,7 +7,11 @@ describe('logOnce', () => { const sandbox = createSandbox() before(() => { - logSpy = sandbox.spy(console, 'log') + logSpy = sandbox.stub(console, 'log') + }) + + after(() => { + sandbox.restore() }) it('should log each message once.', () => { diff --git a/test/node/src/logging.test.ts b/test/node/src/logging.test.ts new file mode 100644 index 000000000..84333b234 --- /dev/null +++ b/test/node/src/logging.test.ts @@ -0,0 +1,183 @@ +import { SinonSandbox, SinonSpy, createSandbox } from 'sinon' +import { Database, expect } from './test-setup' +import { + DatabaseConnection, + Driver, + DummyDriver, + Kysely, + LogConfig, + PostgresDialect, +} from '../../..' + +describe('logging', () => { + let sandbox: SinonSandbox + let errorSpy: SinonSpy + let logSpy: SinonSpy + + beforeEach(() => { + sandbox = createSandbox() + errorSpy = sandbox.stub(console, 'error') + logSpy = sandbox.stub(console, 'log') + }) + + afterEach(() => { + sandbox.restore() + }) + + describe('when query execution succeeds', () => { + describe('when query logging is disabled', () => { + describe('when error logging is disabled', () => { + const db = getKysely([]) + + it('should not log query', async () => { + await run(db) + expect(logSpy.called).to.be.false + }) + + it('should not log error', async () => { + await run(db) + expect(errorSpy.called).to.be.false + }) + }) + + describe('when error logging is enabled', () => { + const db = getKysely(['error']) + + it('should not log query', async () => { + await run(db) + expect(logSpy.called).to.be.false + }) + + it('should not log error', async () => { + await run(db) + expect(errorSpy.called).to.be.false + }) + }) + }) + + describe('when query logging is enabled', () => { + describe('when error logging is disabled', () => { + const db = getKysely(['query']) + + it('should log query', async () => { + await run(db) + expect(logSpy.called).to.be.true + }) + + it('should not log error', async () => { + await run(db) + expect(errorSpy.called).to.be.false + }) + }) + + describe('when error logging is enabled', () => { + const db = getKysely(['query', 'error']) + + it('should log query', async () => { + await run(db) + expect(logSpy.called).to.be.true + }) + + it('should not log error', async () => { + await run(db) + expect(errorSpy.called).to.be.false + }) + }) + }) + }) + + describe('when query execution fails', () => { + const executeQuery = () => Promise.reject('oops') + + describe('when query logging is disabled', () => { + describe('when error logging is disabled', () => { + const db = getKysely([], executeQuery) + + it('should not log query', async () => { + await run(db) + expect(logSpy.called).to.be.false + }) + + it('should not log error', async () => { + await run(db) + expect(errorSpy.called).to.be.false + }) + }) + + describe('when error logging is enabled', () => { + const db = getKysely(['error'], executeQuery) + + it('should not log query', async () => { + await run(db) + expect(logSpy.called).to.be.false + }) + + it('should log error', async () => { + await run(db) + expect(errorSpy.called).to.be.true + }) + }) + }) + + describe('when query logging is enabled', () => { + describe('when error logging is disabled', () => { + const db = getKysely(['query'], executeQuery) + + it('should not log query', async () => { + await run(db) + expect(logSpy.called).to.be.false + }) + + it('should not log error', async () => { + await run(db) + expect(errorSpy.called).to.be.false + }) + }) + + describe('when error logging is enabled', () => { + const db = getKysely(['query', 'error'], executeQuery) + + it('should not log query', async () => { + await run(db) + expect(logSpy.called).to.be.false + }) + + it('should log error', async () => { + await run(db) + expect(errorSpy.called).to.be.true + }) + }) + }) + }) +}) + +function getKysely( + log: LogConfig, + executeQuery: DatabaseConnection['executeQuery'] = () => + Promise.resolve({ rows: [] }), +): Kysely { + return new Kysely({ + dialect: new (class extends PostgresDialect { + constructor() { + super({ pool: {} as any }) + } + createDriver(): Driver { + return new (class extends DummyDriver { + acquireConnection(): Promise { + return Promise.resolve({ + executeQuery, + streamQuery: (async () => {}) as any, + }) + } + })() + } + })(), + log, + }) +} + +async function run(db: Kysely) { + try { + await db.selectFrom('person').selectAll().execute() + } catch (err) {} +} diff --git a/test/node/src/merge.test.ts b/test/node/src/merge.test.ts new file mode 100644 index 000000000..568a3d910 --- /dev/null +++ b/test/node/src/merge.test.ts @@ -0,0 +1,1098 @@ +import { MergeResult, sql } from '../../..' +import { + DIALECTS, + NOT_SUPPORTED, + TestContext, + clearDatabase, + destroyTest, + expect, + initTest, + insertDefaultDataSet, + testSql, +} from './test-setup.js' + +for (const dialect of DIALECTS.filter( + (dialect) => dialect === 'postgres' || dialect === 'mssql', +)) { + describe(`merge (${dialect})`, () => { + let ctx: TestContext + + before(async function () { + ctx = await initTest(this, dialect) + }) + + beforeEach(async () => { + await insertDefaultDataSet(ctx) + }) + + afterEach(async () => { + await clearDatabase(ctx) + }) + + after(async () => { + await destroyTest(ctx) + }) + + describe('using', () => { + it('should perform a merge...using table simple on...when matched then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenDelete() + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then delete', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then delete;', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(3n) + }) + + it('should perform a merge...using table alias simple on alias...when matched then delete query', async () => { + const query = ctx.db + .mergeInto('person as pr') + .using('pet as pt', 'pt.owner_id', 'pr.id') + .whenMatched() + .thenDelete() + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" as "pr" using "pet" as "pt" on "pt"."owner_id" = "pr"."id" when matched then delete', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" as "pr" using "pet" as "pt" on "pt"."owner_id" = "pr"."id" when matched then delete;', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(3n) + }) + + it('should perform a merge...using table complex on...when matched then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', (on) => + on + .onRef('pet.owner_id', '=', 'person.id') + .on('pet.name', '=', 'Lucky'), + ) + .whenMatched() + .thenDelete() + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" and "pet"."name" = $1 when matched then delete', + parameters: ['Lucky'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" and "pet"."name" = @1 when matched then delete;', + parameters: ['Lucky'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should perform a merge...using subquery simple on...when matched then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .using( + ctx.db + .selectFrom('pet') + .select('owner_id') + .where('name', '=', 'Lucky') + .as('pet'), + 'pet.owner_id', + 'person.id', + ) + .whenMatched() + .thenDelete() + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using (select "owner_id" from "pet" where "name" = $1) as "pet" on "pet"."owner_id" = "person"."id" when matched then delete', + parameters: ['Lucky'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using (select "owner_id" from "pet" where "name" = @1) as "pet" on "pet"."owner_id" = "person"."id" when matched then delete;', + parameters: ['Lucky'], + }, + sqlite: NOT_SUPPORTED, + }) + }) + }) + + describe('whenMatched', () => { + it('should perform a merge...using table simple on...when matched and simple binary then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatchedAnd('person.gender', '=', 'female') + .thenDelete() + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched and "person"."gender" = $1 then delete', + parameters: ['female'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched and "person"."gender" = @1 then delete;', + parameters: ['female'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(1n) + }) + + it('should perform a merge...using table simple on...when matched and simple binary cross ref then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatchedAndRef('person.first_name', '=', 'pet.name') + .thenDelete() + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched and "person"."first_name" = "pet"."name" then delete', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched and "person"."first_name" = "pet"."name" then delete;', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should perform a merge...using table simple on...when matched and complex and then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatchedAnd((eb) => + eb('person.gender', '=', 'female').and( + 'person.first_name', + '=', + eb.ref('pet.name'), + ), + ) + .thenDelete() + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched and ("person"."gender" = $1 and "person"."first_name" = "pet"."name") then delete', + parameters: ['female'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched and ("person"."gender" = @1 and "person"."first_name" = "pet"."name") then delete;', + parameters: ['female'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should perform a merge...using table simple on...when matched and complex or then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatchedAnd((eb) => + eb('person.gender', '=', 'female').or( + 'person.first_name', + '=', + eb.ref('pet.name'), + ), + ) + .thenDelete() + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched and ("person"."gender" = $1 or "person"."first_name" = "pet"."name") then delete', + parameters: ['female'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched and ("person"."gender" = @1 or "person"."first_name" = "pet"."name") then delete;', + parameters: ['female'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(1n) + }) + + if (dialect === 'postgres') { + it('should perform a merge...using table...when matched then do nothing query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenDoNothing() + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then do nothing', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + } + + describe('update', () => { + it('should perform a merge...using table simple on...when matched then update set object query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenUpdateSet({ + middle_name: 'pet owner', + }) + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then update set "middle_name" = $1', + parameters: ['pet owner'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then update set "middle_name" = @1;', + parameters: ['pet owner'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(3n) + }) + + it('should perform a merge...using table simple on...when matched then update set object ref query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenUpdateSet((eb) => ({ + first_name: eb.ref('person.last_name'), + middle_name: eb.ref('pet.name'), + })) + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then update set "first_name" = "person"."last_name", "middle_name" = "pet"."name"', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then update set "first_name" = "person"."last_name", "middle_name" = "pet"."name";', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(3n) + }) + + it('should perform a merge...using table simple on...when matched then update set column query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenUpdateSet('middle_name', 'pet owner') + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then update set "middle_name" = $1', + parameters: ['pet owner'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then update set "middle_name" = @1;', + parameters: ['pet owner'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(3n) + }) + + it('should perform a merge...using table simple on...when matched then update set column ref query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenUpdateSet('first_name', (eb) => eb.ref('person.last_name')) + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then update set "first_name" = "person"."last_name"', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then update set "first_name" = "person"."last_name";', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(3n) + }) + + it('should perform a merge...using table simple on...when matched then update set column cross ref query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenUpdateSet('middle_name', (eb) => eb.ref('pet.name')) + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then update set "middle_name" = "pet"."name"', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then update set "middle_name" = "pet"."name";', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(3n) + }) + + it('should perform a merge...using table simple on...when matched then update set complex query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenUpdate((ub) => + ub + .set('first_name', (eb) => eb.ref('person.last_name')) + .set('middle_name', (eb) => eb.ref('pet.name')) + .set({ + marital_status: 'single', + }), + ) + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then update set "first_name" = "person"."last_name", "middle_name" = "pet"."name", "marital_status" = $1', + parameters: ['single'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then update set "first_name" = "person"."last_name", "middle_name" = "pet"."name", "marital_status" = @1;', + parameters: ['single'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(3n) + }) + }) + }) + + describe('whenNotMatched', () => { + if (dialect === 'postgres') { + it('should perform a merge...using table simple on...when not matched then do nothing query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatched() + .thenDoNothing() + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched then do nothing', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + } + + describe('insert', () => { + it('should perform a merge...using table complex on...when not matched then insert values query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', (on) => + on + .onRef('pet.owner_id', '=', 'person.id') + .on('pet.name', '=', 'NO_SUCH_PET_NAME'), + ) + .whenNotMatched() + .thenInsertValues({ + gender: 'male', + first_name: 'Dingo', + middle_name: 'the', + last_name: 'Dog', + }) + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" and "pet"."name" = $1 when not matched then insert ("gender", "first_name", "middle_name", "last_name") values ($2, $3, $4, $5)', + parameters: ['NO_SUCH_PET_NAME', 'male', 'Dingo', 'the', 'Dog'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" and "pet"."name" = @1 when not matched then insert ("gender", "first_name", "middle_name", "last_name") values (@2, @3, @4, @5);', + parameters: ['NO_SUCH_PET_NAME', 'male', 'Dingo', 'the', 'Dog'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(3n) + }) + + describe('And', () => { + it('should perform a merge...using table simple on...when not matched and simple binary then insert values query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedAnd('pet.name', '=', 'Dingo') + .thenInsertValues({ + gender: 'male', + first_name: 'Dingo', + middle_name: 'the', + last_name: 'Dog', + }) + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched and "pet"."name" = $1 then insert ("gender", "first_name", "middle_name", "last_name") values ($2, $3, $4, $5)', + parameters: ['Dingo', 'male', 'Dingo', 'the', 'Dog'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched and "pet"."name" = @1 then insert ("gender", "first_name", "middle_name", "last_name") values (@2, @3, @4, @5);', + parameters: ['Dingo', 'male', 'Dingo', 'the', 'Dog'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should perform a merge...using table simple on...when not matched and simple binary ref then insert values query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedAndRef('pet.name', '=', 'pet.species') + .thenInsertValues({ + gender: 'male', + first_name: 'Dingo', + middle_name: 'the', + last_name: 'Dog', + }) + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched and "pet"."name" = "pet"."species" then insert ("gender", "first_name", "middle_name", "last_name") values ($1, $2, $3, $4)', + parameters: ['male', 'Dingo', 'the', 'Dog'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched and "pet"."name" = "pet"."species" then insert ("gender", "first_name", "middle_name", "last_name") values (@1, @2, @3, @4);', + parameters: ['male', 'Dingo', 'the', 'Dog'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should perform a merge...using table simple on...when not matched and complex and then insert values query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedAnd((eb) => + eb('pet.name', '=', 'Dingo').and( + 'pet.name', + '=', + eb.ref('pet.name'), + ), + ) + .thenInsertValues({ + gender: 'male', + first_name: 'Dingo', + middle_name: 'the', + last_name: 'Dog', + }) + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched and ("pet"."name" = $1 and "pet"."name" = "pet"."name") then insert ("gender", "first_name", "middle_name", "last_name") values ($2, $3, $4, $5)', + parameters: ['Dingo', 'male', 'Dingo', 'the', 'Dog'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched and ("pet"."name" = @1 and "pet"."name" = "pet"."name") then insert ("gender", "first_name", "middle_name", "last_name") values (@2, @3, @4, @5);', + parameters: ['Dingo', 'male', 'Dingo', 'the', 'Dog'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should perform a merge...using table simple on...when not matched and complex or then insert values query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedAnd((eb) => + eb('pet.name', '=', 'Dingo').or( + 'pet.name', + '=', + eb.ref('pet.name'), + ), + ) + .thenInsertValues({ + gender: 'male', + first_name: 'Dingo', + middle_name: 'the', + last_name: 'Dog', + }) + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched and ("pet"."name" = $1 or "pet"."name" = "pet"."name") then insert ("gender", "first_name", "middle_name", "last_name") values ($2, $3, $4, $5)', + parameters: ['Dingo', 'male', 'Dingo', 'the', 'Dog'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched and ("pet"."name" = @1 or "pet"."name" = "pet"."name") then insert ("gender", "first_name", "middle_name", "last_name") values (@2, @3, @4, @5);', + parameters: ['Dingo', 'male', 'Dingo', 'the', 'Dog'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + }) + + it('should perform a merge...using table complex on...when not matched then insert values cross ref query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', (on) => on.on('pet.owner_id', 'is', null)) + .whenNotMatched() + .thenInsertValues((eb) => ({ + gender: 'other', + first_name: eb.ref('pet.name'), + middle_name: 'the', + last_name: eb.ref('pet.species'), + })) + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" is null when not matched then insert ("gender", "first_name", "middle_name", "last_name") values ($1, "pet"."name", $2, "pet"."species")', + parameters: ['other', 'the'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" is null when not matched then insert ("gender", "first_name", "middle_name", "last_name") values (@1, "pet"."name", @2, "pet"."species");', + parameters: ['other', 'the'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(3n) + }) + }) + + if (dialect === 'mssql') { + describe('BySource', () => { + it('should perform a merge...using table simple on...when not matched by source then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedBySource() + .thenDelete() + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched by source then delete;', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + describe('And', () => { + it('should perform a merge...using table simple on...when not matched by source and simple binary then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedBySourceAnd('person.first_name', '=', 'Jennifer') + .thenDelete() + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched by source and "person"."first_name" = @1 then delete;', + parameters: ['Jennifer'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should perform a merge...using table simple on...when not matched by source and simple binary ref then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedBySourceAndRef( + 'person.first_name', + '=', + 'person.last_name', + ) + .thenDelete() + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched by source and "person"."first_name" = "person"."last_name" then delete;', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should perform a merge...using table simple on...when not matched by source and complex and then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedBySourceAnd((eb) => + eb('person.gender', '=', 'female').and( + 'person.first_name', + '=', + eb.ref('person.last_name'), + ), + ) + .thenDelete() + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched by source and ("person"."gender" = @1 and "person"."first_name" = "person"."last_name") then delete;', + parameters: ['female'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should perform a merge...using table simple on...when not matched by source and complex or then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedBySourceAnd((eb) => + eb('person.gender', '=', 'female').or( + 'person.first_name', + '=', + eb.ref('person.last_name'), + ), + ) + .thenDelete() + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched by source and ("person"."gender" = @1 or "person"."first_name" = "person"."last_name") then delete;', + parameters: ['female'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + }) + + describe('update', () => { + it('should perform a merge...using table simple on...when not matched by source then update set object query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedBySource() + .thenUpdateSet({ + middle_name: 'pet owner', + }) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched by source then update set "middle_name" = @1;', + parameters: ['pet owner'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should perform a merge...using table simple on...when not matched by source then update set object ref query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedBySource() + .thenUpdateSet((eb) => ({ + first_name: eb.ref('person.last_name'), + })) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched by source then update set "first_name" = "person"."last_name";', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should perform a merge...using table simple on...when not matched by source then update set column query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedBySource() + .thenUpdateSet('middle_name', 'pet owner') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched by source then update set "middle_name" = @1;', + parameters: ['pet owner'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should perform a merge...using table simple on...when not matched by source then update set column ref query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedBySource() + .thenUpdateSet('first_name', (eb) => eb.ref('person.last_name')) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched by source then update set "first_name" = "person"."last_name";', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should perform a merge...using table simple on...when not matched by source then update set complex query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenNotMatchedBySource() + .thenUpdate((ub) => + ub + .set('first_name', (eb) => eb.ref('person.last_name')) + .set({ + marital_status: 'single', + }), + ) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when not matched by source then update set "first_name" = "person"."last_name", "marital_status" = @1;', + parameters: ['single'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(0n) + }) + }) + }) + } + }) + + describe('multiple whens', () => { + it('should perform a merge...using table simple on...when matched then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenDelete() + .whenNotMatched() + .thenInsertValues((eb) => ({ + gender: 'other', + first_name: eb.ref('pet.name'), + middle_name: 'the', + last_name: eb.ref('pet.species'), + })) + + testSql(query, dialect, { + postgres: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then delete when not matched then insert ("gender", "first_name", "middle_name", "last_name") values ($1, "pet"."name", $2, "pet"."species")', + parameters: ['other', 'the'], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then delete when not matched then insert ("gender", "first_name", "middle_name", "last_name") values (@1, "pet"."name", @2, "pet"."species");', + parameters: ['other', 'the'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(3n) + }) + }) + + if (dialect === 'mssql') { + it('should perform a merge top...using table simple on...when matched then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .top(1) + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenDelete() + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge top(1) into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then delete;', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(1n) + }) + + it('should perform a merge top percent...using table simple on...when matched then delete query', async () => { + const query = ctx.db + .mergeInto('person') + .top(50, 'percent') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenDelete() + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge top(50) percent into "person" using "pet" on "pet"."owner_id" = "person"."id" when matched then delete;', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirstOrThrow() + + expect(result).to.be.instanceOf(MergeResult) + expect(result.numChangedRows).to.equal(2n) + }) + + it('should perform a merge...using table simple on...when matched then delete output id query', async () => { + const expected = await ctx.db.selectFrom('pet').select('id').execute() + + const query = ctx.db + .mergeInto('pet') + .using('person', 'pet.owner_id', 'person.id') + .whenMatched() + .thenDelete() + .output('deleted.id') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "pet" using "person" on "pet"."owner_id" = "person"."id" when matched then delete output "deleted"."id";', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.execute() + + expect(result).to.eql(expected) + }) + + it('should perform a merge...using table simple on...when matched then update set name output deleted.name, inserted.name query', async () => { + const query = ctx.db + .mergeInto('pet') + .using('person', 'pet.owner_id', 'person.id') + .whenMatched() + .thenUpdateSet((eb) => ({ + name: sql`${eb.ref('person.first_name')} + '''s pet'`, + })) + .output(['deleted.name as old_name', 'inserted.name as new_name']) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'merge into "pet" using "person" on "pet"."owner_id" = "person"."id" when matched then update set "name" = "person"."first_name" + \'\'\'s pet\' output "deleted"."name" as "old_name", "inserted"."name" as "new_name";', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.execute() + + expect(result).to.eql([ + { old_name: 'Catto', new_name: "Jennifer's pet" }, + { old_name: 'Doggo', new_name: "Arnold's pet" }, + { old_name: 'Hammo', new_name: "Sylvester's pet" }, + ]) + }) + } + }) +} diff --git a/test/node/src/migration.test.ts b/test/node/src/migration.test.ts index 739ef3b11..4fca280ff 100644 --- a/test/node/src/migration.test.ts +++ b/test/node/src/migration.test.ts @@ -13,12 +13,12 @@ import { } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, expect, initTest, TestContext, + DIALECTS, } from './test-setup.js' const CUSTOM_MIGRATION_SCHEMA = 'migrate' @@ -123,13 +123,42 @@ for (const dialect of DIALECTS) { expect(error).to.be.an.instanceOf(Error) expect(getMessage(error)).to.eql( - 'corrupted migrations: expected previously executed migration migration3 to be at index 1 but migration2 was found in its place. New migrations must always have a name that comes alphabetically after the last executed migration.' + 'corrupted migrations: expected previously executed migration migration3 to be at index 1 but migration2 was found in its place. New migrations must always have a name that comes alphabetically after the last executed migration.', ) expect(executedUpMethods1).to.eql(['migration1', 'migration3']) expect(executedUpMethods2).to.eql([]) }) + it('should run a new migration added before the last executed one with allowUnorderedMigrations enabled', async () => { + const [migrator1, executedUpMethods1] = createMigrations( + ['migration1', 'migration3'], + { allowUnorderedMigrations: true }, + ) + + const { results: results1 } = await migrator1.migrateToLatest() + + const [migrator2, executedUpMethods2] = createMigrations( + ['migration1', 'migration2', 'migration3', 'migration4'], + { allowUnorderedMigrations: true }, + ) + + const { results: results2 } = await migrator2.migrateToLatest() + + expect(results1).to.eql([ + { migrationName: 'migration1', direction: 'Up', status: 'Success' }, + { migrationName: 'migration3', direction: 'Up', status: 'Success' }, + ]) + + expect(results2).to.eql([ + { migrationName: 'migration2', direction: 'Up', status: 'Success' }, + { migrationName: 'migration4', direction: 'Up', status: 'Success' }, + ]) + + expect(executedUpMethods1).to.eql(['migration1', 'migration3']) + expect(executedUpMethods2).to.eql(['migration2', 'migration4']) + }) + it('should return an error if a previously executed migration is missing', async () => { const [migrator1, executedUpMethods1] = createMigrations([ 'migration1', @@ -149,7 +178,7 @@ for (const dialect of DIALECTS) { expect(error).to.be.an.instanceOf(Error) expect(getMessage(error)).to.eql( - 'corrupted migrations: previously executed migration migration1 is missing' + 'corrupted migrations: previously executed migration migration1 is missing', ) expect(executedUpMethods1).to.eql([ @@ -178,7 +207,7 @@ for (const dialect of DIALECTS) { expect(error).to.be.an.instanceOf(Error) expect(getMessage(error)).to.eql( - 'corrupted migrations: previously executed migration migration3 is missing' + 'corrupted migrations: previously executed migration migration3 is missing', ) expect(executedUpMethods1).to.eql([ @@ -189,6 +218,63 @@ for (const dialect of DIALECTS) { expect(executedUpMethods2).to.eql([]) }) + describe('with allowUnorderedMigrations', () => { + it('should return an error if a previously executed migration is missing', async () => { + const [migrator1, executedUpMethods1] = createMigrations( + ['migration1', 'migration2', 'migration3'], + { allowUnorderedMigrations: true }, + ) + + await migrator1.migrateToLatest() + + const [migrator2, executedUpMethods2] = createMigrations( + ['migration2', 'migration3', 'migration4'], + { allowUnorderedMigrations: true }, + ) + + const { error } = await migrator2.migrateToLatest() + + expect(error).to.be.an.instanceOf(Error) + expect(getMessage(error)).to.eql( + 'corrupted migrations: previously executed migration migration1 is missing', + ) + + expect(executedUpMethods1).to.eql([ + 'migration1', + 'migration2', + 'migration3', + ]) + expect(executedUpMethods2).to.eql([]) + }) + + it('should return an error if a the last executed migration is not found', async () => { + const [migrator1, executedUpMethods1] = createMigrations( + ['migration1', 'migration2', 'migration3'], + { allowUnorderedMigrations: true }, + ) + + const [migrator2, executedUpMethods2] = createMigrations( + ['migration1', 'migration2', 'migration4'], + { allowUnorderedMigrations: true }, + ) + + await migrator1.migrateToLatest() + const { error } = await migrator2.migrateToLatest() + + expect(error).to.be.an.instanceOf(Error) + expect(getMessage(error)).to.eql( + 'corrupted migrations: previously executed migration migration3 is missing', + ) + + expect(executedUpMethods1).to.eql([ + 'migration1', + 'migration2', + 'migration3', + ]) + expect(executedUpMethods2).to.eql([]) + }) + }) + it('should return an error if one of the migrations fails', async () => { const [migrator, executedUpMethods] = createMigrations([ 'migration1', @@ -369,6 +455,149 @@ for (const dialect of DIALECTS) { expect(executedUpMethods2).to.eql([]) expect(executedDownMethods2).to.eql(['migration4', 'migration3']) }) + + describe('with allowUnorderedMigrations enabled', () => { + it('should migrate up to a specific migration', async () => { + const [migrator1, executedUpMethods1] = createMigrations( + ['migration1', 'migration3', 'migration4', 'migration5'], + { allowUnorderedMigrations: true }, + ) + + const { results: results1 } = await migrator1.migrateTo('migration3') + + const [migrator2, executedUpMethods2] = createMigrations( + [ + 'migration1', + 'migration2', + 'migration3', + 'migration4', + 'migration5', + ], + { allowUnorderedMigrations: true }, + ) + + const { results: results2 } = await migrator2.migrateTo('migration4') + + expect(results1).to.eql([ + { migrationName: 'migration1', direction: 'Up', status: 'Success' }, + { migrationName: 'migration3', direction: 'Up', status: 'Success' }, + ]) + + expect(results2).to.eql([ + { migrationName: 'migration2', direction: 'Up', status: 'Success' }, + { migrationName: 'migration4', direction: 'Up', status: 'Success' }, + ]) + + expect(executedUpMethods1).to.eql(['migration1', 'migration3']) + expect(executedUpMethods2).to.eql(['migration2', 'migration4']) + }) + + it('should migrate all the way down', async () => { + const [migrator1, executedUpMethods1] = createMigrations( + ['migration1', 'migration2', 'migration4'], + { allowUnorderedMigrations: true }, + ) + + const { results: results1 } = await migrator1.migrateToLatest() + + const [migrator2, executedUpMethods2, executedDownMethods2] = + createMigrations( + ['migration1', 'migration2', 'migration3', 'migration4'], + { allowUnorderedMigrations: true }, + ) + + const { results: results2 } = await migrator2.migrateTo(NO_MIGRATIONS) + + expect(results1).to.eql([ + { migrationName: 'migration1', direction: 'Up', status: 'Success' }, + { migrationName: 'migration2', direction: 'Up', status: 'Success' }, + { migrationName: 'migration4', direction: 'Up', status: 'Success' }, + ]) + + expect(results2).to.eql([ + { + migrationName: 'migration4', + direction: 'Down', + status: 'Success', + }, + { + migrationName: 'migration2', + direction: 'Down', + status: 'Success', + }, + { + migrationName: 'migration1', + direction: 'Down', + status: 'Success', + }, + ]) + + expect(executedUpMethods1).to.eql([ + 'migration1', + 'migration2', + 'migration4', + ]) + expect(executedUpMethods2).to.eql([]) + expect(executedDownMethods2).to.eql([ + 'migration4', + 'migration2', + 'migration1', + ]) + }) + + it('should migrate down to a specific migration', async () => { + const [migrator1, executedUpMethods1] = createMigrations( + ['migration1', 'migration2', 'migration3', 'migration5'], + { allowUnorderedMigrations: true }, + ) + + const { results: results1 } = await migrator1.migrateTo('migration5') + + const [migrator2, executedUpMethods2, executedDownMethods2] = + createMigrations( + [ + 'migration1', + 'migration2', + 'migration3', + 'migration4', + 'migration5', + ], + { allowUnorderedMigrations: true }, + ) + + const { results: results2 } = await migrator2.migrateTo('migration2') + + expect(results1).to.eql([ + { migrationName: 'migration1', direction: 'Up', status: 'Success' }, + { migrationName: 'migration2', direction: 'Up', status: 'Success' }, + { migrationName: 'migration3', direction: 'Up', status: 'Success' }, + { migrationName: 'migration5', direction: 'Up', status: 'Success' }, + ]) + + expect(results2).to.eql([ + { + migrationName: 'migration5', + direction: 'Down', + status: 'Success', + }, + { + migrationName: 'migration3', + direction: 'Down', + status: 'Success', + }, + ]) + + expect(executedUpMethods1).to.eql([ + 'migration1', + 'migration2', + 'migration3', + 'migration5', + ]) + + expect(executedUpMethods2).to.eql([]) + expect(executedDownMethods2).to.eql(['migration5', 'migration3']) + }) + }) }) describe('migrateUp', () => { @@ -399,6 +628,65 @@ for (const dialect of DIALECTS) { expect(results3).to.eql([]) expect(executedUpMethods).to.eql(['migration1', 'migration2']) }) + + it('should return an error when migrating up if a new migration is added before the last executed one', async () => { + const [migrator1, executedUpMethods1] = createMigrations([ + 'migration1', + 'migration3', + ]) + + await migrator1.migrateToLatest() + + const [migrator2, executedUpMethods2] = createMigrations([ + 'migration1', + 'migration2', + 'migration3', + 'migration4', + ]) + + const { error } = await migrator2.migrateUp() + + expect(error).to.be.an.instanceOf(Error) + expect(getMessage(error)).to.eql( + 'corrupted migrations: expected previously executed migration migration3 to be at index 1 but migration2 was found in its place. New migrations must always have a name that comes alphabetically after the last executed migration.', + ) + + expect(executedUpMethods1).to.eql(['migration1', 'migration3']) + expect(executedUpMethods2).to.eql([]) + }) + + it('should migrate up one step with allowUnorderedMigrations enabled', async () => { + const [migrator1, executedUpMethods1] = createMigrations( + ['migration1', 'migration3'], + { allowUnorderedMigrations: true }, + ) + + const { results: results1 } = await migrator1.migrateToLatest() + + const [migrator2, executedUpMethods2] = createMigrations( + ['migration1', 'migration2', 'migration3', 'migration4'], + { allowUnorderedMigrations: true }, + ) + + const { results: results2 } = await migrator2.migrateUp() + const { results: results3 } = await migrator2.migrateUp() + + expect(results1).to.eql([ + { migrationName: 'migration1', direction: 'Up', status: 'Success' }, + { migrationName: 'migration3', direction: 'Up', status: 'Success' }, + ]) + + expect(results2).to.eql([ + { migrationName: 'migration2', direction: 'Up', status: 'Success' }, + ]) + + expect(results3).to.eql([ + { migrationName: 'migration4', direction: 'Up', status: 'Success' }, + ]) + + expect(executedUpMethods1).to.eql(['migration1', 'migration3']) + expect(executedUpMethods2).to.eql(['migration2', 'migration4']) + }) }) describe('migrateDown', () => { @@ -431,6 +719,79 @@ for (const dialect of DIALECTS) { expect(executedUpMethods).to.eql(['migration1', 'migration2']) expect(executedDownMethods).to.eql(['migration2', 'migration1']) }) + + it('should return an error if a new migration is added before the last executed one', async () => { + const [migrator1, executedUpMethods1] = createMigrations([ + 'migration1', + 'migration3', + ]) + + await migrator1.migrateToLatest() + + const [migrator2, _executedUpMethods2, executedDownMethods2] = + createMigrations(['migration1', 'migration2', 'migration3']) + + const { error } = await migrator2.migrateDown() + + expect(error).to.be.an.instanceOf(Error) + expect(getMessage(error)).to.eql( + 'corrupted migrations: expected previously executed migration migration3 to be at index 1 but migration2 was found in its place. New migrations must always have a name that comes alphabetically after the last executed migration.', + ) + + expect(executedUpMethods1).to.eql(['migration1', 'migration3']) + expect(executedDownMethods2).to.eql([]) + }) + + it('should migrate down one step with allowUnorderedMigrations enabled', async () => { + const [migrator1, executedUpMethods1, _executedDownMethods1] = + createMigrations(['migration1', 'migration2', 'migration4'], { + allowUnorderedMigrations: true, + }) + + await migrator1.migrateToLatest() + + const [migrator2, _executedUpMethods2, executedDownMethods2] = + createMigrations( + [ + 'migration1', + 'migration2', + 'migration3', + 'migration4', + 'migration5', + ], + { allowUnorderedMigrations: true }, + ) + + const { results: results1 } = await migrator2.migrateDown() + const { results: results2 } = await migrator2.migrateDown() + const { results: results3 } = await migrator2.migrateDown() + const { results: results4 } = await migrator2.migrateDown() + + expect(results1).to.eql([ + { migrationName: 'migration4', direction: 'Down', status: 'Success' }, + ]) + + expect(results2).to.eql([ + { migrationName: 'migration2', direction: 'Down', status: 'Success' }, + ]) + + expect(results3).to.eql([ + { migrationName: 'migration1', direction: 'Down', status: 'Success' }, + ]) + + expect(results4).to.eql([]) + + expect(executedUpMethods1).to.eql([ + 'migration1', + 'migration2', + 'migration4', + ]) + expect(executedDownMethods2).to.eql([ + 'migration4', + 'migration2', + 'migration1', + ]) + }) }) if (dialect === 'postgres') { @@ -442,7 +803,7 @@ for (const dialect of DIALECTS) { migrationTableName: CUSTOM_MIGRATION_TABLE, migrationLockTableName: CUSTOM_MIGRATION_LOCK_TABLE, migrationTableSchema: CUSTOM_MIGRATION_SCHEMA, - } + }, ) let promises: Promise[] = [] @@ -461,20 +822,20 @@ for (const dialect of DIALECTS) { expect( await doesTableExists( CUSTOM_MIGRATION_LOCK_TABLE, - CUSTOM_MIGRATION_SCHEMA - ) + CUSTOM_MIGRATION_SCHEMA, + ), ).to.equal(true) expect( await doesTableExists( CUSTOM_MIGRATION_LOCK_TABLE, - CUSTOM_MIGRATION_SCHEMA - ) + CUSTOM_MIGRATION_SCHEMA, + ), ).to.equal(true) expect(await doesTableExists(DEFAULT_MIGRATION_TABLE)).to.equal(false) expect(await doesTableExists(DEFAULT_MIGRATION_LOCK_TABLE)).to.equal( - false + false, ) }) }) @@ -513,7 +874,7 @@ for (const dialect of DIALECTS) { function createMigrations( migrationConfigs: (string | { name: string; error?: string })[], - migratorConfig?: Partial + migratorConfig?: Partial, ): [Migrator, string[], string[]] { const executedUpMethods: string[] = [] const executedDownMethods: string[] = [] @@ -548,7 +909,7 @@ for (const dialect of DIALECTS) { }, } }, - {} + {}, ) return [ @@ -566,11 +927,11 @@ for (const dialect of DIALECTS) { async function doesTableExists( tableName: string, - schema?: string + schema?: string, ): Promise { const tables = await ctx.db.introspection.getTables() return !!tables.find( - (it) => it.name === tableName && (!schema || it.schema === schema) + (it) => it.name === tableName && (!schema || it.schema === schema), ) } diff --git a/test/node/src/order-by.test.ts b/test/node/src/order-by.test.ts index e42121d60..f205c2c44 100644 --- a/test/node/src/order-by.test.ts +++ b/test/node/src/order-by.test.ts @@ -1,7 +1,6 @@ import { sql } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -10,6 +9,7 @@ import { expect, NOT_SUPPORTED, insertDefaultDataSet, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -32,7 +32,7 @@ for (const dialect of DIALECTS) { await destroyTest(ctx) }) - it('order by one column', async () => { + it('should order by one column', async () => { const query = ctx.db .selectFrom('person') .selectAll() @@ -47,6 +47,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` order by `first_name`', parameters: [], }, + mssql: { + sql: 'select * from "person" order by "first_name"', + parameters: [], + }, sqlite: { sql: 'select * from "person" order by "first_name"', parameters: [], @@ -63,7 +67,7 @@ for (const dialect of DIALECTS) { ]) }) - it('order by two columns', async () => { + it('should order by two columns in two invocations', async () => { const query = ctx.db .selectFrom('person') .selectAll() @@ -79,6 +83,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` order by `first_name`, `last_name` desc', parameters: [], }, + mssql: { + sql: 'select * from "person" order by "first_name", "last_name" desc', + parameters: [], + }, sqlite: { sql: 'select * from "person" order by "first_name", "last_name" desc', parameters: [], @@ -88,23 +96,86 @@ for (const dialect of DIALECTS) { await query.execute() }) - it('order by aliased column', async () => { + it('should order by two columns in one invocations', async () => { const query = ctx.db .selectFrom('person') - .select('first_name as fn') + .selectAll() + .orderBy(['first_name', 'last_name desc']) + + testSql(query, dialect, { + postgres: { + sql: 'select * from "person" order by "first_name", "last_name" desc', + parameters: [], + }, + mysql: { + sql: 'select * from `person` order by `first_name`, `last_name` desc', + parameters: [], + }, + mssql: { + sql: 'select * from "person" order by "first_name", "last_name" desc', + parameters: [], + }, + sqlite: { + sql: 'select * from "person" order by "first_name", "last_name" desc', + parameters: [], + }, + }) + + await query.execute() + }) + + it('should order by aliased columns', async () => { + const query = ctx.db + .selectFrom('person') + .select([ + 'first_name as fn', + 'middle_name as mn', + 'last_name as ln', + 'gender as g', + ]) .orderBy('fn') + .orderBy('mn asc') + .orderBy(['ln desc', 'g']) testSql(query, dialect, { postgres: { - sql: 'select "first_name" as "fn" from "person" order by "fn"', + sql: [ + 'select "first_name" as "fn",', + '"middle_name" as "mn",', + '"last_name" as "ln",', + '"gender" as "g"', + 'from "person" order by "fn", "mn" asc, "ln" desc, "g"', + ], parameters: [], }, mysql: { - sql: 'select `first_name` as `fn` from `person` order by `fn`', + sql: [ + 'select `first_name` as `fn`,', + '`middle_name` as `mn`,', + '`last_name` as `ln`,', + '`gender` as `g`', + 'from `person` order by `fn`, `mn` asc, `ln` desc, `g`', + ], + parameters: [], + }, + mssql: { + sql: [ + 'select "first_name" as "fn",', + '"middle_name" as "mn",', + '"last_name" as "ln",', + '"gender" as "g"', + 'from "person" order by "fn", "mn" asc, "ln" desc, "g"', + ], parameters: [], }, sqlite: { - sql: 'select "first_name" as "fn" from "person" order by "fn"', + sql: [ + 'select "first_name" as "fn",', + '"middle_name" as "mn",', + '"last_name" as "ln",', + '"gender" as "g"', + 'from "person" order by "fn", "mn" asc, "ln" desc, "g"', + ], parameters: [], }, }) @@ -112,11 +183,68 @@ for (const dialect of DIALECTS) { await query.execute() }) - it('order by raw expression', async () => { + it('should order by expressions', async () => { const query = ctx.db .selectFrom('person') .selectAll() - .orderBy(sql`coalesce(${sql.ref('first_name')}, 'foo')`, 'asc') + .orderBy(sql`coalesce(${sql.ref('first_name')}, ${sql.lit('foo')}) asc`) + .orderBy((eb) => eb.fn.coalesce('last_name', sql.lit('foo'))) + .orderBy([ + sql`coalesce(${sql.ref('gender')}, ${sql.lit('foo')})`, + (eb) => sql`${eb.fn.coalesce('middle_name', sql.lit('foo'))} desc`, + ]) + + testSql(query, dialect, { + postgres: { + sql: [ + 'select * from "person"', + `order by coalesce("first_name", 'foo') asc,`, + `coalesce("last_name", 'foo'),`, + `coalesce("gender", 'foo'),`, + `coalesce("middle_name", 'foo') desc`, + ], + parameters: [], + }, + mysql: { + sql: [ + 'select * from `person`', + "order by coalesce(`first_name`, 'foo') asc,", + "coalesce(`last_name`, 'foo'),", + "coalesce(`gender`, 'foo'),", + "coalesce(`middle_name`, 'foo') desc", + ], + parameters: [], + }, + mssql: { + sql: [ + 'select * from "person"', + `order by coalesce("first_name", 'foo') asc,`, + `coalesce("last_name", 'foo'),`, + `coalesce("gender", 'foo'),`, + `coalesce("middle_name", 'foo') desc`, + ], + parameters: [], + }, + sqlite: { + sql: [ + 'select * from "person"', + `order by coalesce("first_name", 'foo') asc,`, + `coalesce("last_name", 'foo'),`, + `coalesce("gender", 'foo'),`, + `coalesce("middle_name", 'foo') desc`, + ], + parameters: [], + }, + }) + + await query.execute() + }) + + it('order by raw expression and a direction', async () => { + const query = ctx.db + .selectFrom('person') + .selectAll() + .orderBy((eb) => eb.fn.coalesce('first_name', sql.lit('foo')), 'asc') testSql(query, dialect, { postgres: { @@ -127,6 +255,10 @@ for (const dialect of DIALECTS) { sql: "select * from `person` order by coalesce(`first_name`, 'foo') asc", parameters: [], }, + mssql: { + sql: `select * from "person" order by coalesce("first_name", 'foo') asc`, + parameters: [], + }, sqlite: { sql: `select * from "person" order by coalesce("first_name", 'foo') asc`, parameters: [], @@ -149,6 +281,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) diff --git a/test/node/src/parse-json-results-plugin.test.ts b/test/node/src/parse-json-results-plugin.test.ts new file mode 100644 index 000000000..c529657c7 --- /dev/null +++ b/test/node/src/parse-json-results-plugin.test.ts @@ -0,0 +1,27 @@ +import { ParseJSONResultsPlugin } from '../../..' +import { createQueryId } from '../../../dist/cjs/util/query-id.js' + +describe('ParseJSONResultsPlugin', () => { + describe("when `objectStrategy` is 'create'", () => { + let plugin: ParseJSONResultsPlugin + + beforeEach(() => { + plugin = new ParseJSONResultsPlugin({ objectStrategy: 'create' }) + }) + + it('should parse JSON results that contain readonly arrays/objects', async () => { + await plugin.transformResult({ + queryId: createQueryId(), + result: { + rows: [ + Object.freeze({ + id: 1, + carIds: Object.freeze([1, 2, 3]), + metadata: JSON.stringify({ foo: 'bar' }), + }), + ], + }, + }) + }) + }) +}) diff --git a/test/node/src/performance.test.ts b/test/node/src/performance.test.ts index db389782b..3059a4f38 100644 --- a/test/node/src/performance.test.ts +++ b/test/node/src/performance.test.ts @@ -42,14 +42,14 @@ if (DIALECTS.includes('postgres')) { selectFrom('toy_schema.toy').whereRef( 'toy_schema.toy.id', '=', - 'toy.id' - ) - ) + 'toy.id', + ), + ), ) .select([ 'toy.price as price', sql`concat(${sql.ref('first_name')}, ' ', ${sql.ref( - 'last_name' + 'last_name', )})`.as('full_name'), ]) .compile() @@ -71,7 +71,7 @@ if (DIALECTS.includes('postgres')) { console.log( 'query building time:', (t1.getTime() - t0.getTime()) / TEST_ROUNDS, - 'ms' + 'ms', ) }) }) diff --git a/test/node/src/raw-query.test.ts b/test/node/src/raw-query.test.ts index 5113a6bfb..f5726682e 100644 --- a/test/node/src/raw-query.test.ts +++ b/test/node/src/raw-query.test.ts @@ -1,7 +1,6 @@ import { sql } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -9,6 +8,7 @@ import { expect, insertDefaultDataSet, testSql, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -37,11 +37,13 @@ for (const dialect of DIALECTS) { const result = await sql<{ first_name: string }>`select first_name from person where gender = ${gender} order by first_name asc, last_name asc`.execute( - ctx.db + ctx.db, ) expect(result.insertId).to.equal(undefined) - expect(result.numUpdatedOrDeletedRows).to.equal(undefined) + expect(result.numAffectedRows).to.equal( + dialect === 'mssql' ? 2n : undefined, + ) expect(result.rows).to.eql([ { first_name: 'Arnold' }, { first_name: 'Sylvester' }, @@ -54,10 +56,10 @@ for (const dialect of DIALECTS) { const result = await sql`update person set first_name = ${newFirstName} where gender = ${gender}`.execute( - ctx.db + ctx.db, ) - expect(result.numUpdatedOrDeletedRows).to.equal(2n) + expect(result.numAffectedRows).to.equal(2n) expect(result.rows).to.eql([]) }) @@ -67,11 +69,11 @@ for (const dialect of DIALECTS) { const result = await sql`delete from person where gender = ${gender}`.execute(ctx.db) - expect(result.numUpdatedOrDeletedRows).to.equal(2n) + expect(result.numAffectedRows).to.equal(2n) expect(result.rows).to.eql([]) }) - if (dialect === 'postgres') { + if (dialect === 'postgres' || dialect === 'sqlite') { it('should run a raw insert query', async () => { const firstName = 'New' const lastName = 'Personsson' @@ -79,7 +81,7 @@ for (const dialect of DIALECTS) { const result = await sql`insert into person (first_name, last_name, gender) values (${firstName}, ${lastName}, ${gender}) returning first_name, last_name`.execute( - ctx.db + ctx.db, ) expect(result.insertId).to.equal(undefined) @@ -87,7 +89,9 @@ for (const dialect of DIALECTS) { { first_name: 'New', last_name: 'Personsson' }, ]) }) - } else { + } + + if (dialect === 'mysql') { it('should run a raw insert query', async () => { const firstName = 'New' const lastName = 'Personsson' @@ -95,7 +99,7 @@ for (const dialect of DIALECTS) { const result = await sql`insert into person (first_name, last_name, gender) values (${firstName}, ${lastName}, ${gender})`.execute( - ctx.db + ctx.db, ) expect(result.insertId! > 0n).to.be.equal(true) @@ -117,6 +121,10 @@ for (const dialect of DIALECTS) { sql: 'select first_name from person where gender = ? order by first_name asc, last_name asc', parameters: [gender], }, + mssql: { + sql: 'select first_name from person where gender = @1 order by first_name asc, last_name asc', + parameters: [gender], + }, sqlite: { sql: 'select first_name from person where gender = ? order by first_name asc, last_name asc', parameters: [gender], diff --git a/test/node/src/raw-sql.test.ts b/test/node/src/raw-sql.test.ts index 761b4a944..2d1af2dca 100644 --- a/test/node/src/raw-sql.test.ts +++ b/test/node/src/raw-sql.test.ts @@ -1,7 +1,6 @@ -import { sql, CompiledQuery } from '../../../' +import { sql, CompiledQuery, DefaultQueryCompiler } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -10,6 +9,7 @@ import { testSql, NOT_SUPPORTED, expect, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -36,7 +36,7 @@ for (const dialect of DIALECTS) { const query = ctx.db .selectFrom('person') .selectAll() - .where(sql`first_name between ${'A'} and ${'B'}`) + .where(sql`first_name between ${'A'} and ${'B'}`) testSql(query, dialect, { postgres: { @@ -47,6 +47,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where first_name between ? and ?', parameters: ['A', 'B'], }, + mssql: { + sql: 'select * from "person" where first_name between @1 and @2', + parameters: ['A', 'B'], + }, sqlite: { sql: 'select * from "person" where first_name between ? and ?', parameters: ['A', 'B'], @@ -56,11 +60,47 @@ for (const dialect of DIALECTS) { await query.execute() }) - it('sql.unsafeLiteral should turn substitutions from parameters into literal values', async () => { + it('substitutions should accept queries', async () => { + const compiler = new DefaultQueryCompiler() + + let node = sql`before ${ctx.db + .selectFrom('person') + .selectAll()} after`.toOperationNode() + expect(compiler.compileQuery(node).sql).to.equal( + `before (select * from "person") after`, + ) + + node = sql`before ${ctx.db.insertInto('person').values({ + first_name: 'Jennifer', + last_name: 'Aniston', + gender: 'female', + })} after`.toOperationNode() + expect(compiler.compileQuery(node).sql).to.equal( + `before insert into "person" ("first_name", "last_name", "gender") values ($1, $2, $3) after`, + ) + + node = sql`before ${ctx.db + .deleteFrom('person') + .where('id', '=', 1)} after`.toOperationNode() + expect(compiler.compileQuery(node).sql).to.equal( + `before delete from "person" where "id" = $1 after`, + ) + + node = sql`before ${ctx.db + .updateTable('person') + .set('first_name', 'Jennifer')} after`.toOperationNode() + expect(compiler.compileQuery(node).sql).to.equal( + `before update "person" set "first_name" = $1 after`, + ) + }) + + it('sql.lit should turn substitutions from parameters into literal values', async () => { const query = ctx.db .selectFrom('person') .selectAll() - .where(sql`first_name between ${sql.lit('A')} and ${sql.lit('B')}`) + .where( + sql`first_name between ${sql.lit('A')} and ${sql.lit('B')}`, + ) testSql(query, dialect, { postgres: { @@ -71,6 +111,10 @@ for (const dialect of DIALECTS) { sql: "select * from `person` where first_name between 'A' and 'B'", parameters: [], }, + mssql: { + sql: `select * from "person" where first_name between 'A' and 'B'`, + parameters: [], + }, sqlite: { sql: `select * from "person" where first_name between 'A' and 'B'`, parameters: [], @@ -84,7 +128,7 @@ for (const dialect of DIALECTS) { const query = ctx.db .selectFrom('person') .selectAll() - .where(sql`${sql.id('first_name')} between ${'A'} and ${'B'}`) + .where(sql`${sql.id('first_name')} between ${'A'} and ${'B'}`) testSql(query, dialect, { postgres: { @@ -95,6 +139,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where `first_name` between ? and ?', parameters: ['A', 'B'], }, + mssql: { + sql: 'select * from "person" where "first_name" between @1 and @2', + parameters: ['A', 'B'], + }, sqlite: { sql: 'select * from "person" where "first_name" between ? and ?', parameters: ['A', 'B'], @@ -104,17 +152,17 @@ for (const dialect of DIALECTS) { await query.execute() }) - if (dialect == 'postgres') { + if (dialect === 'postgres' || dialect === 'mssql') { it('sql.id should separate multiple arguments by dots', async () => { const query = ctx.db .selectFrom('person') .selectAll() .where( - sql`${sql.id( - 'public', + sql`${sql.id( + dialect === 'postgres' ? 'public' : 'dbo', 'person', - 'first_name' - )} between ${'A'} and ${'B'}` + 'first_name', + )} between ${'A'} and ${'B'}`, ) testSql(query, dialect, { @@ -123,6 +171,10 @@ for (const dialect of DIALECTS) { parameters: ['A', 'B'], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'select * from "person" where "dbo"."person"."first_name" between @1 and @2', + parameters: ['A', 'B'], + }, sqlite: NOT_SUPPORTED, }) @@ -134,7 +186,7 @@ for (const dialect of DIALECTS) { const query = ctx.db .selectFrom('person') .selectAll() - .where(sql`${sql.ref('first_name')} between ${'A'} and ${'B'}`) + .where(sql`${sql.ref('first_name')} between ${'A'} and ${'B'}`) testSql(query, dialect, { postgres: { @@ -145,6 +197,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where `first_name` between ? and ?', parameters: ['A', 'B'], }, + mssql: { + sql: 'select * from "person" where "first_name" between @1 and @2', + parameters: ['A', 'B'], + }, sqlite: { sql: 'select * from "person" where "first_name" between ? and ?', parameters: ['A', 'B'], @@ -154,15 +210,15 @@ for (const dialect of DIALECTS) { await query.execute() }) - if (dialect === 'postgres') { + if (dialect === 'postgres' || dialect === 'mssql') { it('sql.ref should support schemas and table names', async () => { const query = ctx.db .selectFrom('person') .selectAll() .where( - sql`${sql.ref( - 'public.person.first_name' - )} between ${'A'} and ${'B'}` + sql`${sql.ref( + `${dialect === 'postgres' ? 'public' : 'dbo'}.person.first_name`, + )} between ${'A'} and ${'B'}`, ) testSql(query, dialect, { @@ -171,6 +227,10 @@ for (const dialect of DIALECTS) { parameters: ['A', 'B'], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'select * from "person" where "dbo"."person"."first_name" between @1 and @2', + parameters: ['A', 'B'], + }, sqlite: NOT_SUPPORTED, }) @@ -192,6 +252,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` as `person`', parameters: [], }, + mssql: { + sql: 'select * from "person" as "person"', + parameters: [], + }, sqlite: { sql: 'select * from "person" as "person"', parameters: [], @@ -201,10 +265,14 @@ for (const dialect of DIALECTS) { await query.execute() }) - if (dialect === 'postgres') { + if (dialect === 'postgres' || dialect === 'mssql') { it('sql.table should support schemas', async () => { const query = ctx.db - .selectFrom(sql`${sql.table('public.person')}`.as('person')) + .selectFrom( + sql`${sql.table( + `${dialect === 'postgres' ? 'public' : 'dbo'}.person`, + )}`.as('person'), + ) .selectAll() testSql(query, dialect, { @@ -213,6 +281,10 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'select * from "dbo"."person" as "person"', + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -226,7 +298,7 @@ for (const dialect of DIALECTS) { const query = ctx.db .selectFrom('person') .selectAll() - .where(sql`first_name in (${sql.join(names)})`) + .where(sql`first_name in (${sql.join(names)})`) testSql(query, dialect, { postgres: { @@ -237,6 +309,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where first_name in (?, ?)', parameters: names, }, + mssql: { + sql: 'select * from "person" where first_name in (@1, @2)', + parameters: names, + }, sqlite: { sql: 'select * from "person" where first_name in (?, ?)', parameters: names, @@ -253,7 +329,9 @@ for (const dialect of DIALECTS) { const query = ctx.db .selectFrom('person') .selectAll() - .where(sql`first_name in (${sql.join(names, sql`::varchar,`)})`) + .where( + sql`first_name in (${sql.join(names, sql`::varchar,`)})`, + ) testSql(query, dialect, { postgres: { @@ -261,6 +339,7 @@ for (const dialect of DIALECTS) { parameters: names, }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -272,10 +351,12 @@ for (const dialect of DIALECTS) { it('CompiledQuery should support raw query with parameters', async () => { const query = CompiledQuery.raw( 'select * from "person" where "public"."person"."first_name" between $1 and $2', - ['A', 'B'] + ['A', 'B'], + ) + expect(query.sql).to.equal( + 'select * from "person" where "public"."person"."first_name" between $1 and $2', ) - expect(query.sql).to.equal('select * from "person" where "public"."person"."first_name" between $1 and $2'); - expect(query.parameters).to.deep.equal(['A', 'B']); + expect(query.parameters).to.deep.equal(['A', 'B']) await ctx.db.executeQuery(query) }) } @@ -290,7 +371,7 @@ for (const dialect of DIALECTS) { sql.ref('id'), sql.lit(9.99).as('price'), ])} from ${sql.table('pet')} where ${sql.ref( - 'name' + 'name', )} = ${'Hammo'}`.execute(ctx.db) const wheel = await ctx.db diff --git a/test/node/src/replace.test.ts b/test/node/src/replace.test.ts index aa13b7c34..9611e68c5 100644 --- a/test/node/src/replace.test.ts +++ b/test/node/src/replace.test.ts @@ -50,6 +50,7 @@ if (DIALECTS.includes('mysql')) { sql: 'replace into `person` (`id`, `first_name`, `last_name`, `gender`) values (?, ?, ?, ?)', parameters: [15, 'Foo', 'Barson', 'other'], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -84,6 +85,7 @@ if (DIALECTS.includes('mysql')) { sql: "replace into `person` (`id`, `first_name`, `last_name`, `gender`) values (?, (select max(name) as `max_name` from `pet`), concat('Bar', 'son'), ?)", parameters: [2500, 'other'], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -101,7 +103,7 @@ if (DIALECTS.includes('mysql')) { .replaceInto('person') .columns(['first_name', 'gender']) .expression((eb) => - eb.selectFrom('pet').select(['name', sql`${'other'}`.as('gender')]) + eb.selectFrom('pet').select(['name', sql`${'other'}`.as('gender')]), ) testSql(query, dialect, { @@ -110,6 +112,7 @@ if (DIALECTS.includes('mysql')) { sql: 'replace into `person` (`first_name`, `gender`) select `name`, ? as `gender` from `pet`', parameters: ['other'], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -144,6 +147,7 @@ if (DIALECTS.includes('mysql')) { sql: 'replace into `person` (`id`, `gender`) values (?, ?)', parameters: [12, 'male'], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -172,6 +176,7 @@ if (DIALECTS.includes('mysql')) { ], }, postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -191,7 +196,7 @@ if (DIALECTS.includes('mysql')) { }) async function getNewestPerson( - db: Kysely + db: Kysely, ): Promise | undefined> { return await db .selectFrom('person') @@ -199,7 +204,7 @@ if (DIALECTS.includes('mysql')) { .where( 'id', '=', - db.selectFrom('person').select(sql`max(id)`.as('max_id')) + db.selectFrom('person').select(sql`max(id)`.as('max_id')), ) .executeTakeFirst() } diff --git a/test/node/src/sanitize-identifiers.test.ts b/test/node/src/sanitize-identifiers.test.ts index c3ef407ee..24673672f 100644 --- a/test/node/src/sanitize-identifiers.test.ts +++ b/test/node/src/sanitize-identifiers.test.ts @@ -1,12 +1,13 @@ import { Updateable } from '../../../dist/cjs' import { - DIALECTS, destroyTest, initTest, TestContext, Person, testSql, + NOT_SUPPORTED, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -39,6 +40,10 @@ for (const dialect of DIALECTS) { sql: 'update `person` set `first_name` = ?, `last_name"``` = ?', parameters: ['foo', 'bar'], }, + mssql: { + sql: 'update "person" set "first_name" = @1, "last_name""`" = @2', + parameters: ['foo', 'bar'], + }, sqlite: { sql: 'update "person" set "first_name" = ?, "last_name""`" = ?', parameters: ['foo', 'bar'], @@ -64,6 +69,10 @@ for (const dialect of DIALECTS) { sql: 'update `person` set `first_name` = ?, `last_name""````` = ?', parameters: ['foo', 'bar'], }, + mssql: { + sql: 'update "person" set "first_name" = @1, "last_name""""``" = @2', + parameters: ['foo', 'bar'], + }, sqlite: { sql: 'update "person" set "first_name" = ?, "last_name""""``" = ?', parameters: ['foo', 'bar'], diff --git a/test/node/src/schema.test.ts b/test/node/src/schema.test.ts index 0ac4f0b39..624b77267 100644 --- a/test/node/src/schema.test.ts +++ b/test/node/src/schema.test.ts @@ -1,7 +1,7 @@ +import { fail } from 'assert' import { ColumnMetadata, sql } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, expect, @@ -9,6 +9,7 @@ import { NOT_SUPPORTED, TestContext, testSql, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -40,7 +41,7 @@ for (const dialect of DIALECTS) { .references('test.a') .onDelete('cascade') .onUpdate('restrict') - .check(sql`b < a`) + .check(sql`b < a`), ) .addColumn('c', 'varchar') .addColumn('d', 'varchar(10)') @@ -55,7 +56,7 @@ for (const dialect of DIALECTS) { .addColumn('m', 'date') .addColumn('n', 'timestamptz') .addColumn('o', 'uuid', (col) => - col.defaultTo(sql`gen_random_uuid()`) + col.defaultTo(sql`gen_random_uuid()`), ) .addColumn('p', 'int2') .addColumn('q', 'int4') @@ -64,11 +65,12 @@ for (const dialect of DIALECTS) { col .generatedAlwaysAs(sql`f + g`) .stored() - .notNull() + .notNull(), ) .addColumn('t', 'time(6)') + .addColumn('tz', 'timetz(6)') .addColumn('u', 'timestamp(6)', (col) => - col.notNull().defaultTo(sql`current_timestamp`) + col.notNull().defaultTo(sql`current_timestamp`), ) .addColumn('v', 'timestamptz(6)') .addColumn('w', 'char(4)') @@ -99,21 +101,24 @@ for (const dialect of DIALECTS) { '"r" int8,', '"s" double precision generated always as (f + g) stored not null,', '"t" time(6),', + '"tz" timetz(6),', '"u" timestamp(6) default current_timestamp not null,', '"v" timestamptz(6),', '"w" char(4),', '"x" char,', - '"y" bytea)' + '"y" bytea)', ], parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) await builder.execute() expect(await getColumnMeta('test.a')).to.eql({ + comment: undefined, dataType: 'int4', dataTypeSchema: 'pg_catalog', isAutoIncrementing: true, @@ -123,6 +128,7 @@ for (const dialect of DIALECTS) { }) expect(await getColumnMeta('test.b')).to.eql({ + comment: undefined, dataType: 'int4', dataTypeSchema: 'pg_catalog', isAutoIncrementing: false, @@ -132,6 +138,7 @@ for (const dialect of DIALECTS) { }) expect(await getColumnMeta('test.l')).to.eql({ + comment: undefined, dataType: 'bool', dataTypeSchema: 'pg_catalog', isAutoIncrementing: false, @@ -140,19 +147,65 @@ for (const dialect of DIALECTS) { name: 'l', }) }) + + it('should create a table with "unique nulls not distinct" modifier for a column', async () => { + const builder = ctx.db.schema + .createTable('test') + .addColumn('a', 'varchar(10)', (builder) => + builder.unique().nullsNotDistinct(), + ) + .addColumn('b', 'varchar(20)') + + testSql(builder, dialect, { + postgres: { + sql: 'create table "test" ("a" varchar(10) unique nulls not distinct, "b" varchar(20))', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + + it('should create a table with "unique nulls not distinct" and other modifiers', async () => { + const builder = ctx.db.schema + .createTable('test') + .addColumn('a', 'integer', (builder) => + builder + .check(sql`a < 100`) + .nullsNotDistinct() + .unique() + .defaultTo(10), + ) + .addColumn('b', 'varchar(20)') + + testSql(builder, dialect, { + postgres: { + sql: 'create table "test" ("a" integer default 10 unique nulls not distinct check (a < 100), "b" varchar(20))', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) } else if (dialect === 'mysql') { it('should create a table with all data types', async () => { const builder = ctx.db.schema .createTable('test') .addColumn('a', 'integer', (col) => - col.primaryKey().autoIncrement() + col.primaryKey().autoIncrement(), ) .addColumn('b', 'integer', (col) => - col.references('test.a').onDelete('cascade').onUpdate('set null') + col.references('test.a').onDelete('cascade').onUpdate('set null'), ) .addColumn('c', 'varchar(255)') .addColumn('d', 'bigint', (col) => - col.unsigned().unique().notNull() + col.unsigned().unique().notNull(), ) .addColumn('e', 'double precision') .addColumn('f', 'real') @@ -169,16 +222,17 @@ for (const dialect of DIALECTS) { col .generatedAlwaysAs(sql`e + f`) .stored() - .notNull() + .notNull(), ) .addColumn('q', 'time(6)') .addColumn('r', 'datetime(6)') .addColumn('s', 'timestamp(6)', (col) => - col.notNull().defaultTo(sql`current_timestamp(6)`) + col.notNull().defaultTo(sql`current_timestamp(6)`), ) .addColumn('t', 'char(4)') .addColumn('u', 'char') .addColumn('v', 'binary(16)') + .addColumn('w', 'varbinary(16)') testSql(builder, dialect, { mysql: { @@ -205,17 +259,20 @@ for (const dialect of DIALECTS) { '`s` timestamp(6) default current_timestamp(6) not null,', '`t` char(4),', '`u` char,', - '`v` binary(16))' + '`v` binary(16),', + '`w` varbinary(16))', ], parameters: [], }, postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) await builder.execute() expect(await getColumnMeta('test.a')).to.eql({ + comment: undefined, dataType: 'int', isAutoIncrementing: true, isNullable: false, @@ -224,6 +281,7 @@ for (const dialect of DIALECTS) { }) expect(await getColumnMeta('test.b')).to.eql({ + comment: undefined, dataType: 'int', isAutoIncrementing: false, isNullable: true, @@ -232,6 +290,7 @@ for (const dialect of DIALECTS) { }) expect(await getColumnMeta('test.k')).to.eql({ + comment: undefined, dataType: 'tinyint', isAutoIncrementing: false, isNullable: false, @@ -239,19 +298,104 @@ for (const dialect of DIALECTS) { name: 'k', }) }) - } else { + } else if (dialect === 'mssql') { + it('should create a table with all data types', async () => { + const builder = ctx.db.schema + .createTable('test') + .addColumn('a', 'integer', (col) => + col.identity().notNull().primaryKey(), + ) + .addColumn('b', 'integer', (col) => + col + .references('test.a') + .onDelete('no action') + .onUpdate('no action') + .check(sql`b < 10`), + ) + .addColumn('c', 'varchar') + .addColumn('d', 'varchar(10)') + .addColumn('e', 'bigint', (col) => col.unique().notNull()) + .addColumn('f', 'double precision') + .addColumn('g', 'real') + .addColumn('h', 'text') + .addColumn('i', sql`varchar(123)`) + .addColumn('j', 'numeric(6, 2)') + .addColumn('k', 'decimal(8, 4)') + .addColumn('l', sql`bit`, (col) => col.notNull().defaultTo(0)) + .addColumn('m', 'date') + .addColumn('n', 'datetime', (col) => + col.defaultTo(sql`current_timestamp`), + ) + .addColumn('o', sql`uniqueidentifier`, (col) => + col.notNull().defaultTo(sql`newid()`), + ) + .addColumn('p', sql`smallint`) + .addColumn('q', sql`int`) + .addColumn('r', 'double precision', (col) => col.notNull()) + .addColumn('s', 'time(6)') + .addColumn('t', 'timestamp', (col) => col.notNull()) + .addColumn('u', sql`datetime2`) + .addColumn('v', 'char(4)') + .addColumn('w', 'char') + .addColumn('x', 'binary') + .addColumn('y', sql``, (col) => col.modifyEnd(sql`as (a + f)`)) + .addColumn('z', 'varbinary') + .addColumn('aa', 'varbinary(16)') + + testSql(builder, dialect, { + mssql: { + sql: [ + 'create table "test"', + '("a" integer identity not null primary key,', + '"b" integer references "test" ("a") on delete no action on update no action check (b < 10),', + '"c" varchar,', + '"d" varchar(10),', + '"e" bigint not null unique,', + '"f" double precision,', + '"g" real,', + '"h" text,', + '"i" varchar(123),', + '"j" numeric(6, 2),', + '"k" decimal(8, 4),', + '"l" bit default 0 not null,', + '"m" date,', + '"n" datetime default current_timestamp,', + '"o" uniqueidentifier default newid() not null,', + '"p" smallint,', + '"q" int,', + '"r" double precision not null,', + '"s" time(6),', + '"t" timestamp not null,', + '"u" datetime2,', + '"v" char(4),', + '"w" char,', + '"x" binary,', + '"y" as (a + f),', + '"z" varbinary,', + '"aa" varbinary(16))', + ], + parameters: [], + }, + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + } else if (dialect === 'sqlite') { it('should create a table with all data types', async () => { const builder = ctx.db.schema .createTable('test') .addColumn('a', 'integer', (col) => - col.primaryKey().autoIncrement().notNull() + col.primaryKey().autoIncrement().notNull(), ) .addColumn('b', 'integer', (col) => col .references('test.a') .onDelete('cascade') .onUpdate('restrict') - .check(sql`b < a`) + .check(sql`b < a`), ) .addColumn('c', 'varchar') .addColumn('d', 'varchar(10)') @@ -272,11 +416,12 @@ for (const dialect of DIALECTS) { col .generatedAlwaysAs(sql`f + g`) .stored() - .notNull() + .notNull(), ) .addColumn('s', 'blob') testSql(builder, dialect, { + mssql: NOT_SUPPORTED, sqlite: { sql: [ 'create table "test"', @@ -309,6 +454,7 @@ for (const dialect of DIALECTS) { await builder.execute() expect(await getColumnMeta('test.a')).to.eql({ + comment: undefined, dataType: 'INTEGER', isAutoIncrementing: true, isNullable: false, @@ -317,6 +463,7 @@ for (const dialect of DIALECTS) { }) expect(await getColumnMeta('test.b')).to.eql({ + comment: undefined, dataType: 'INTEGER', isAutoIncrementing: false, isNullable: true, @@ -325,6 +472,7 @@ for (const dialect of DIALECTS) { }) expect(await getColumnMeta('test.l')).to.eql({ + comment: undefined, dataType: 'boolean', isAutoIncrementing: false, isNullable: false, @@ -332,6 +480,8 @@ for (const dialect of DIALECTS) { name: 'l', }) }) + } else { + throw new Error(`Unknown dialect: ${dialect}`) } it('should create a table with a unique constraints', async () => { @@ -352,6 +502,10 @@ for (const dialect of DIALECTS) { sql: 'create table `test` (`a` varchar(255), `b` varchar(255), `c` varchar(255), constraint `a_b_unique` unique (`a`, `b`), constraint `b_c_unique` unique (`b`, `c`))', parameters: [], }, + mssql: { + sql: 'create table "test" ("a" varchar(255), "b" varchar(255), "c" varchar(255), constraint "a_b_unique" unique ("a", "b"), constraint "b_c_unique" unique ("b", "c"))', + parameters: [], + }, sqlite: { sql: 'create table "test" ("a" varchar(255), "b" varchar(255), "c" varchar(255), constraint "a_b_unique" unique ("a", "b"), constraint "b_c_unique" unique ("b", "c"))', parameters: [], @@ -361,6 +515,30 @@ for (const dialect of DIALECTS) { await builder.execute() }) + if (dialect === 'postgres') { + it('should create a table with a unique constraint and "nulls not distinct" option', async () => { + const builder = ctx.db.schema + .createTable('test') + .addColumn('a', 'varchar(255)') + .addColumn('b', 'varchar(255)') + .addUniqueConstraint('a_b_unique', ['a', 'b'], (uc) => + uc.nullsNotDistinct(), + ) + + testSql(builder, dialect, { + postgres: { + sql: 'create table "test" ("a" varchar(255), "b" varchar(255), constraint "a_b_unique" unique nulls not distinct ("a", "b"))', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + } + it('should create a table with check constraints', async () => { const builder = ctx.db.schema .createTable('test') @@ -379,6 +557,10 @@ for (const dialect of DIALECTS) { sql: 'create table `test` (`a` integer, `b` integer, `c` integer, constraint `check_a` check (a > 1), constraint `check_b` check (b < c))', parameters: [], }, + mssql: { + sql: 'create table "test" ("a" integer, "b" integer, "c" integer, constraint "check_a" check (a > 1), constraint "check_b" check (b < c))', + parameters: [], + }, sqlite: { sql: 'create table "test" ("a" integer, "b" integer, "c" integer, constraint "check_a" check (a > 1), constraint "check_b" check (b < c))', parameters: [], @@ -404,6 +586,10 @@ for (const dialect of DIALECTS) { sql: 'create table `test` (`a` integer, `b` integer, constraint `primary` primary key (`a`, `b`))', parameters: [], }, + mssql: { + sql: 'create table "test" ("a" integer, "b" integer, constraint "primary" primary key ("a", "b"))', + parameters: [], + }, sqlite: { sql: 'create table "test" ("a" integer, "b" integer, constraint "primary" primary key ("a", "b"))', parameters: [], @@ -439,6 +625,10 @@ for (const dialect of DIALECTS) { sql: 'create table `test` (`a` integer, `b` integer, constraint `foreign_key` foreign key (`a`, `b`) references `test2` (`c`, `d`))', parameters: [], }, + mssql: { + sql: 'create table "test" ("a" integer, "b" integer, constraint "foreign_key" foreign key ("a", "b") references "test2" ("c", "d"))', + parameters: [], + }, sqlite: { sql: 'create table "test" ("a" integer, "b" integer, constraint "foreign_key" foreign key ("a", "b") references "test2" ("c", "d"))', parameters: [], @@ -448,7 +638,7 @@ for (const dialect of DIALECTS) { await builder.execute() }) - if (dialect === 'postgres') { + if (dialect === 'postgres' || dialect === 'mssql') { it('should support schemas in foreign key target table', async () => { await ctx.db.schema .createTable('test2') @@ -464,8 +654,8 @@ for (const dialect of DIALECTS) { .addForeignKeyConstraint( 'foreign_key', ['a', 'b'], - 'public.test2', - ['c', 'd'] + dialect === 'postgres' ? 'public.test2' : 'dbo.test2', + ['c', 'd'], ) testSql(builder, dialect, { @@ -474,6 +664,10 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'create table "test" ("a" integer, "b" integer, constraint "foreign_key" foreign key ("a", "b") references "dbo"."test2" ("c", "d"))', + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -498,7 +692,7 @@ for (const dialect of DIALECTS) { ['a', 'b'], 'test2', ['c', 'd'], - (cb) => cb.onUpdate('cascade') + (cb) => cb.onUpdate('cascade'), ) testSql(builder, dialect, { @@ -510,56 +704,12 @@ for (const dialect of DIALECTS) { sql: 'create table `test` (`a` integer, `b` integer, constraint `foreign_key` foreign key (`a`, `b`) references `test2` (`c`, `d`) on update cascade)', parameters: [], }, - sqlite: { + mssql: { sql: 'create table "test" ("a" integer, "b" integer, constraint "foreign_key" foreign key ("a", "b") references "test2" ("c", "d") on update cascade)', parameters: [], }, - }) - - await builder.execute() - }) - - it("should create a table if it doesn't already exist", async () => { - const builder = ctx.db.schema - .createTable('test') - .ifNotExists() - .addColumn('id', 'integer', (col) => col.primaryKey()) - - testSql(builder, dialect, { - postgres: { - sql: 'create table if not exists "test" ("id" integer primary key)', - parameters: [], - }, - mysql: { - sql: 'create table if not exists `test` (`id` integer primary key)', - parameters: [], - }, - sqlite: { - sql: 'create table if not exists "test" ("id" integer primary key)', - parameters: [], - }, - }) - - await builder.execute() - }) - - it('should create a temporary table', async () => { - const builder = ctx.db.schema - .createTable('test') - .temporary() - .addColumn('id', 'integer', (col) => col.primaryKey()) - - testSql(builder, dialect, { - postgres: { - sql: 'create temporary table "test" ("id" integer primary key)', - parameters: [], - }, - mysql: { - sql: 'create temporary table `test` (`id` integer primary key)', - parameters: [], - }, sqlite: { - sql: 'create temporary table "test" ("id" integer primary key)', + sql: 'create table "test" ("a" integer, "b" integer, constraint "foreign_key" foreign key ("a", "b") references "test2" ("c", "d") on update cascade)', parameters: [], }, }) @@ -567,147 +717,355 @@ for (const dialect of DIALECTS) { await builder.execute() }) - if (dialect === 'postgres') { - it('should create a temporary table witn on commit statement', async () => { + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'sqlite' + ) { + it("should create a table if it doesn't already exist", async () => { const builder = ctx.db.schema .createTable('test') - .temporary() + .ifNotExists() .addColumn('id', 'integer', (col) => col.primaryKey()) - .onCommit('drop') testSql(builder, dialect, { postgres: { - sql: 'create temporary table "test" ("id" integer primary key) on commit drop', + sql: 'create table if not exists "test" ("id" integer primary key)', + parameters: [], + }, + mysql: { + sql: 'create table if not exists `test` (`id` integer primary key)', + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'create table if not exists "test" ("id" integer primary key)', parameters: [], }, - mysql: NOT_SUPPORTED, - sqlite: NOT_SUPPORTED, }) await builder.execute() }) - } - if (dialect === 'postgres') { - it('should create a table in specific schema', async () => { + it('should create a temporary table', async () => { const builder = ctx.db.schema - .createTable('public.test') - .addColumn('id', 'serial', (col) => col.primaryKey()) - .addColumn('foreign_key', 'integer', (col) => - col.references('public.test.id') - ) + .createTable('test') + .temporary() + .addColumn('id', 'integer', (col) => col.primaryKey()) testSql(builder, dialect, { postgres: { - sql: 'create table "public"."test" ("id" serial primary key, "foreign_key" integer references "public"."test" ("id"))', + sql: 'create temporary table "test" ("id" integer primary key)', + parameters: [], + }, + mysql: { + sql: 'create temporary table `test` (`id` integer primary key)', + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'create temporary table "test" ("id" integer primary key)', parameters: [], }, - mysql: NOT_SUPPORTED, - sqlite: NOT_SUPPORTED, }) await builder.execute() }) - } - if (dialect === 'postgres') { - it('should create a table with generated identity', async () => { + it('should create a table with as expression', async () => { const builder = ctx.db.schema .createTable('test') - .addColumn('id', 'integer', (col) => - col.generatedAlwaysAsIdentity() - ) + .as(ctx.db.selectFrom('person').select(['first_name', 'last_name'])) testSql(builder, dialect, { postgres: { - sql: 'create table "test" ("id" integer generated always as identity)', + sql: 'create table "test" as select "first_name", "last_name" from "person"', + parameters: [], + }, + mysql: { + sql: 'create table `test` as select `first_name`, `last_name` from `person`', + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'create table "test" as select "first_name", "last_name" from "person"', parameters: [], }, - mysql: NOT_SUPPORTED, - sqlite: NOT_SUPPORTED, }) await builder.execute() }) - } - if (dialect === 'postgres') { - it('should create a table with generated identity (by default)', async () => { + it('should create a temporary table if not exists with as expression', async () => { const builder = ctx.db.schema .createTable('test') - .addColumn('id', 'integer', (col) => - col.generatedByDefaultAsIdentity() + .temporary() + .ifNotExists() + .as( + ctx.db + .selectFrom('person') + .select(['first_name', 'last_name']) + .where('first_name', '=', 'Jennifer'), ) testSql(builder, dialect, { postgres: { - sql: 'create table "test" ("id" integer generated by default as identity)', - parameters: [], + sql: 'create temporary table if not exists "test" as select "first_name", "last_name" from "person" where "first_name" = $1', + parameters: ['Jennifer'], + }, + mysql: { + sql: 'create temporary table if not exists `test` as select `first_name`, `last_name` from `person` where `first_name` = ?', + parameters: ['Jennifer'], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'create temporary table if not exists "test" as select "first_name", "last_name" from "person" where "first_name" = ?', + parameters: ['Jennifer'], }, - mysql: NOT_SUPPORTED, - sqlite: NOT_SUPPORTED, }) await builder.execute() }) - } - if (dialect === 'postgres') { - it('should create a global temporary table', async () => { - const builder = ctx.db.schema - .createTable('test') - .modifyFront(sql`global temporary`) - .addColumn('id', 'integer', (col) => col.primaryKey()) - .addColumn('first_name', 'varchar(64)', (col) => col.notNull()) - .addColumn('last_name', 'varchar(64)', (col) => col.notNull()) + it('should create a table with as expression and raw sql', async () => { + let rawSql = sql`select "first_name", "last_name" from "person"` + if (dialect === 'mysql') { + rawSql = sql`select \`first_name\`, \`last_name\` from \`person\`` + } + + const builder = ctx.db.schema.createTable('test').as(rawSql) testSql(builder, dialect, { postgres: { - sql: [ - 'create global temporary table "test"', - '("id" integer primary key,', - '"first_name" varchar(64) not null,', - '"last_name" varchar(64) not null)', - ], + sql: 'create table "test" as select "first_name", "last_name" from "person"', + parameters: [], + }, + mysql: { + sql: 'create table `test` as select `first_name`, `last_name` from `person`', + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'create table "test" as select "first_name", "last_name" from "person"', parameters: [], }, - mysql: NOT_SUPPORTED, - sqlite: NOT_SUPPORTED, }) await builder.execute() }) - } - if (dialect === 'postgres') { - it('should create a table partitioned by country', async () => { + it('should create a table with as expression and ignore addColumn', async () => { const builder = ctx.db.schema .createTable('test') - .addColumn('id', 'integer', (col) => col.notNull()) - .addColumn('nickname', 'varchar(64)', (col) => col.notNull()) - .addColumn('country', 'varchar(2)', (col) => col.notNull()) - .addPrimaryKeyConstraint('test_pk', ['id', 'country']) - .modifyEnd(sql`partition by hash (${sql.ref('country')})`) + .as(ctx.db.selectFrom('person').select(['first_name', 'last_name'])) + .addColumn('first_name', 'varchar(20)') testSql(builder, dialect, { postgres: { - sql: [ - 'create table "test"', - '("id" integer not null,', - '"nickname" varchar(64) not null,', - '"country" varchar(2) not null,', - 'constraint "test_pk" primary key ("id", "country")) partition by hash ("country")', - ], + sql: 'create table "test" as select "first_name", "last_name" from "person"', + parameters: [], + }, + mysql: { + sql: 'create table `test` as select `first_name`, `last_name` from `person`', + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'create table "test" as select "first_name", "last_name" from "person"', parameters: [], }, - mysql: NOT_SUPPORTED, - sqlite: NOT_SUPPORTED, }) await builder.execute() }) - } else if (dialect === 'mysql') { - it('should create a table partitioned by country', async () => { + } + + if (dialect === 'mssql') { + it('should create a temporary table', async () => { + await ctx.db.connection().execute(async (conn) => { + const builder = conn.schema + .createTable('##test') + .addColumn('id', 'integer', (col) => col.primaryKey()) + + testSql(builder, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'create table "##test" ("id" integer primary key)', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + + await sql`select * from "##test"`.execute(conn) + }) + + try { + await sql`select * from "##test"`.execute(ctx.db) + + fail() // table is not gone! + } catch (err) { + // it works! + } + }) + } + + if (dialect === 'postgres') { + it('should create a temporary table with on commit statement', async () => { + const builder = ctx.db.schema + .createTable('test') + .temporary() + .addColumn('id', 'integer', (col) => col.primaryKey()) + .onCommit('drop') + + testSql(builder, dialect, { + postgres: { + sql: 'create temporary table "test" ("id" integer primary key) on commit drop', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + } + + if (dialect === 'postgres' || dialect === 'mssql') { + const schema = dialect === 'postgres' ? 'public' : 'dbo' + + it('should create a table in specific schema', async () => { + const builder = ctx.db.schema + .createTable(`${schema}.test`) + .addColumn('id', 'varchar(32)', (col) => col.primaryKey()) + .addColumn('foreign_key', 'varchar(32)', (col) => + col.references(`${schema}.test.id`), + ) + + testSql(builder, dialect, { + postgres: { + sql: 'create table "public"."test" ("id" varchar(32) primary key, "foreign_key" varchar(32) references "public"."test" ("id"))', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'create table "dbo"."test" ("id" varchar(32) primary key, "foreign_key" varchar(32) references "dbo"."test" ("id"))', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + } + + if (dialect === 'postgres') { + it('should create a table with generated identity', async () => { + const builder = ctx.db.schema + .createTable('test') + .addColumn('id', 'integer', (col) => + col.generatedAlwaysAsIdentity(), + ) + + testSql(builder, dialect, { + postgres: { + sql: 'create table "test" ("id" integer generated always as identity)', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + } + + if (dialect === 'postgres') { + it('should create a table with generated identity (by default)', async () => { + const builder = ctx.db.schema + .createTable('test') + .addColumn('id', 'integer', (col) => + col.generatedByDefaultAsIdentity(), + ) + + testSql(builder, dialect, { + postgres: { + sql: 'create table "test" ("id" integer generated by default as identity)', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + } + + if (dialect === 'postgres') { + it('should create a global temporary table', async () => { + const builder = ctx.db.schema + .createTable('test') + .modifyFront(sql`global temporary`) + .addColumn('id', 'integer', (col) => col.primaryKey()) + .addColumn('first_name', 'varchar(64)', (col) => col.notNull()) + .addColumn('last_name', 'varchar(64)', (col) => col.notNull()) + + testSql(builder, dialect, { + postgres: { + sql: [ + 'create global temporary table "test"', + '("id" integer primary key,', + '"first_name" varchar(64) not null,', + '"last_name" varchar(64) not null)', + ], + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + } + + if (dialect === 'postgres') { + it('should create a table partitioned by country', async () => { + const builder = ctx.db.schema + .createTable('test') + .addColumn('id', 'integer', (col) => col.notNull()) + .addColumn('nickname', 'varchar(64)', (col) => col.notNull()) + .addColumn('country', 'varchar(2)', (col) => col.notNull()) + .addPrimaryKeyConstraint('test_pk', ['id', 'country']) + .modifyEnd(sql`partition by hash (${sql.ref('country')})`) + + testSql(builder, dialect, { + postgres: { + sql: [ + 'create table "test"', + '("id" integer not null,', + '"nickname" varchar(64) not null,', + '"country" varchar(2) not null,', + 'constraint "test_pk" primary key ("id", "country")) partition by hash ("country")', + ], + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + } + + if (dialect === 'mysql') { + it('should create a table partitioned by country', async () => { const builder = ctx.db.schema .createTable('test') .addColumn('id', 'integer', (col) => col.notNull()) @@ -728,12 +1086,15 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) await builder.execute() }) - } else { + } + + if (dialect === 'sqlite') { it('should create a strict table', async () => { const builder = ctx.db.schema .createTable('test') @@ -745,6 +1106,7 @@ for (const dialect of DIALECTS) { testSql(builder, dialect, { postgres: NOT_SUPPORTED, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: [ 'create table "test"', @@ -766,7 +1128,7 @@ for (const dialect of DIALECTS) { .createTable('test') .addColumn('id', 'integer', (col) => col.primaryKey()) .addColumn('first_name', 'varchar(36)', (col) => - col.modifyFront(sql`collate utf8mb4_general_ci`).notNull() + col.modifyFront(sql`collate utf8mb4_general_ci`).notNull(), ) .addColumn('age', 'integer', (col) => col @@ -774,9 +1136,9 @@ for (const dialect of DIALECTS) { .notNull() .modifyEnd( sql`comment ${sql.lit( - 'it is not polite to ask a woman her age' - )}` - ) + 'it is not polite to ask a woman her age', + )}`, + ), ) testSql(builder, dialect, { @@ -790,6 +1152,7 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -803,8 +1166,8 @@ for (const dialect of DIALECTS) { .addColumn('id', 'integer', (col) => col.notNull()) .$call((builder) => builder.addColumn('call_me', 'varchar(10)', (col) => - col.defaultTo('maybe') - ) + col.defaultTo('maybe'), + ), ) testSql(builder, dialect, { @@ -824,6 +1187,14 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + 'create table "test"', + '("id" integer not null,', + `"call_me" varchar(10) default 'maybe')`, + ], + parameters: [], + }, sqlite: { sql: [ 'create table "test"', @@ -858,6 +1229,10 @@ for (const dialect of DIALECTS) { sql: 'drop table `test`', parameters: [], }, + mssql: { + sql: 'drop table "test"', + parameters: [], + }, sqlite: { sql: 'drop table "test"', parameters: [], @@ -879,6 +1254,10 @@ for (const dialect of DIALECTS) { sql: 'drop table if exists `test`', parameters: [], }, + mssql: { + sql: 'drop table if exists "test"', + parameters: [], + }, sqlite: { sql: 'drop table if exists "test"', parameters: [], @@ -887,7 +1266,8 @@ for (const dialect of DIALECTS) { await builder.execute() }) - if (dialect !== 'sqlite') { + + if (dialect == 'postgres' || dialect === 'mysql' || dialect === 'mssql') { it('should drop a table cascade', async () => { const builder = ctx.db.schema.dropTable('test').cascade() testSql(builder, dialect, { @@ -899,6 +1279,10 @@ for (const dialect of DIALECTS) { sql: 'drop table `test` cascade', parameters: [], }, + mssql: { + sql: 'drop table "test" cascade', + parameters: [], + }, sqlite: NOT_SUPPORTED, }) }) @@ -914,6 +1298,10 @@ for (const dialect of DIALECTS) { sql: 'drop table if exists `test` cascade', parameters: [], }, + mssql: { + sql: 'drop table if exists "test" cascade', + parameters: [], + }, sqlite: NOT_SUPPORTED, }) }) @@ -946,6 +1334,10 @@ for (const dialect of DIALECTS) { sql: 'create index `test_first_name_index` on `test` (`first_name`)', parameters: [], }, + mssql: { + sql: 'create index "test_first_name_index" on "test" ("first_name")', + parameters: [], + }, sqlite: { sql: 'create index "test_first_name_index" on "test" ("first_name")', parameters: [], @@ -955,7 +1347,7 @@ for (const dialect of DIALECTS) { await builder.execute() }) - if (dialect !== 'mysql') { + if (dialect === 'postgres' || dialect === 'sqlite') { it('should create an index if not exists', async () => { await ctx.db.schema .createIndex('test_first_name_index') @@ -974,11 +1366,12 @@ for (const dialect of DIALECTS) { sql: 'create index if not exists "test_first_name_index" on "test" ("first_name")', parameters: [], }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: 'create index if not exists "test_first_name_index" on "test" ("first_name")', parameters: [], }, - mysql: NOT_SUPPORTED, }) await builder.execute() @@ -1001,6 +1394,10 @@ for (const dialect of DIALECTS) { sql: 'create unique index `test_first_name_index` on `test` (`first_name`)', parameters: [], }, + mssql: { + sql: 'create unique index "test_first_name_index" on "test" ("first_name")', + parameters: [], + }, sqlite: { sql: 'create unique index "test_first_name_index" on "test" ("first_name")', parameters: [], @@ -1010,7 +1407,7 @@ for (const dialect of DIALECTS) { await builder.execute() }) - if (dialect === 'postgres') { + if (dialect === 'postgres' || dialect === 'mysql') { it('should create an index with a type', async () => { const builder = ctx.db.schema .createIndex('test_first_name_index') @@ -1024,13 +1421,59 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: { - sql: 'create index `test_first_name_index` on `test` using hash (`first_name`)', + sql: 'create index `test_first_name_index` using hash on `test` (`first_name`)', parameters: [], }, - sqlite: { - sql: 'create index "test_first_name_index" on "test" using hash ("first_name")', + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + } + + if (dialect === 'postgres') { + it('should create an index with "nulls not distinct" modifier', async () => { + const builder = ctx.db.schema + .createIndex('test_first_name_index') + .on('test') + .nullsNotDistinct() + .column('first_name') + + testSql(builder, dialect, { + postgres: { + sql: 'create index "test_first_name_index" on "test" ("first_name") nulls not distinct', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + + it('should create an index with "nulls not distinct" and other modifiers', async () => { + const builder = ctx.db.schema + .createIndex('test_first_last_name_index') + .nullsNotDistinct() + .ifNotExists() + .columns(['first_name', 'last_name']) + .using('btree') + .unique() + .where('first_name', 'like', 'test%') + .on('test') + + testSql(builder, dialect, { + postgres: { + sql: + 'create unique index if not exists "test_first_last_name_index" on "test" ' + + 'using btree ("first_name", "last_name") nulls not distinct where "first_name" like \'test%\'', parameters: [], }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, }) await builder.execute() @@ -1052,6 +1495,10 @@ for (const dialect of DIALECTS) { sql: 'create index `test_name_index` on `test` (`first_name`, `last_name`)', parameters: [], }, + mssql: { + sql: 'create index "test_name_index" on "test" ("first_name", "last_name")', + parameters: [], + }, sqlite: { sql: 'create index "test_name_index" on "test" ("first_name", "last_name")', parameters: [], @@ -1061,45 +1508,56 @@ for (const dialect of DIALECTS) { await builder.execute() }) - it('should create an index for an expression', async () => { + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'sqlite' + ) { + it('should create an index for an expression', async () => { + const builder = ctx.db.schema + .createIndex('test_first_name_index') + .on('test') + .expression(sql`(first_name < 'Sami')`) + + testSql(builder, dialect, { + postgres: { + sql: `create index "test_first_name_index" on "test" ((first_name < 'Sami'))`, + parameters: [], + }, + mysql: { + sql: "create index `test_first_name_index` on `test` ((first_name < 'Sami'))", + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: `create index "test_first_name_index" on "test" ((first_name < 'Sami'))`, + parameters: [], + }, + }) + + await builder.execute() + }) + } + + it('should create a sorted index, single column', async () => { const builder = ctx.db.schema - .createIndex('test_first_name_index') + .createIndex('test_descending_first_name_index') .on('test') - .expression(sql`(first_name < 'Sami')`) + .column('first_name desc') testSql(builder, dialect, { postgres: { - sql: `create index "test_first_name_index" on "test" ((first_name < 'Sami'))`, + sql: 'create index "test_descending_first_name_index" on "test" ("first_name" desc)', parameters: [], }, mysql: { - sql: "create index `test_first_name_index` on `test` ((first_name < 'Sami'))", - parameters: [], - }, - sqlite: { - sql: `create index "test_first_name_index" on "test" ((first_name < 'Sami'))`, + sql: 'create index `test_descending_first_name_index` on `test` (`first_name` desc)', parameters: [], }, - }) - - await builder.execute() - }) - - it('should create a sorted index, single column', async () => { - const builder = ctx.db.schema - .createIndex('test_descending_first_name_index') - .on('test') - .column('first_name desc') - - testSql(builder, dialect, { - postgres: { + mssql: { sql: 'create index "test_descending_first_name_index" on "test" ("first_name" desc)', parameters: [], }, - mysql: { - sql: 'create index `test_descending_first_name_index` on `test` (`first_name` desc)', - parameters: [], - }, sqlite: { sql: 'create index "test_descending_first_name_index" on "test" ("first_name" desc)', parameters: [], @@ -1124,6 +1582,10 @@ for (const dialect of DIALECTS) { sql: 'create index `test_first_name_descending_last_name_index` on `test` (`first_name`, `last_name` desc)', parameters: [], }, + mssql: { + sql: 'create index "test_first_name_descending_last_name_index" on "test" ("first_name", "last_name" desc)', + parameters: [], + }, sqlite: { sql: 'create index "test_first_name_descending_last_name_index" on "test" ("first_name", "last_name" desc)', parameters: [], @@ -1133,17 +1595,80 @@ for (const dialect of DIALECTS) { await builder.execute() }) - if (dialect !== 'mysql') { - it('should create a partial index', async () => { + if ( + dialect === 'postgres' || + dialect === 'mssql' || + dialect === 'sqlite' + ) { + it('should create a partial index, single column', async () => { + const builder = ctx.db.schema + .createIndex('test_partial_index') + .on('test') + .column('first_name') + .where('first_name', '=', 'Sami') + + testSql(builder, dialect, { + postgres: { + sql: `create index "test_partial_index" on "test" ("first_name") where "first_name" = 'Sami'`, + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: `create index "test_partial_index" on "test" ("first_name") where "first_name" = 'Sami'`, + parameters: [], + }, + sqlite: { + sql: `create index "test_partial_index" on "test" ("first_name") where "first_name" = 'Sami'`, + parameters: [], + }, + }) + + await builder.execute() + }) + + it('should create a partial index, multi-column, and', async () => { const builder = ctx.db.schema .createIndex('test_partial_index') .on('test') .columns(['first_name', 'last_name']) - .where(({ or, cmpr }) => - or([ - cmpr('first_name', '=', 'Igal'), - cmpr(sql.ref('age'), '>=', 18), - ]) + .where((eb) => + eb.and([ + eb('first_name', '=', 'Igal'), + eb(sql.ref('age'), '>=', 18), + ]), + ) + + testSql(builder, dialect, { + postgres: { + sql: `create index "test_partial_index" on "test" ("first_name", "last_name") where ("first_name" = 'Igal' and "age" >= 18)`, + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: `create index "test_partial_index" on "test" ("first_name", "last_name") where ("first_name" = 'Igal' and "age" >= 18)`, + parameters: [], + }, + sqlite: { + sql: `create index "test_partial_index" on "test" ("first_name", "last_name") where ("first_name" = 'Igal' and "age" >= 18)`, + parameters: [], + }, + }) + + await builder.execute() + }) + } + + if (dialect === 'postgres' || dialect === 'sqlite') { + it('should create a partial index, multi-column, or', async () => { + const builder = ctx.db.schema + .createIndex('test_partial_index') + .on('test') + .columns(['first_name', 'last_name']) + .where((eb) => + eb.or([ + eb('first_name', '=', 'Igal'), + eb(sql.ref('age'), '>=', 18), + ]), ) testSql(builder, dialect, { @@ -1152,6 +1677,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: `create index "test_partial_index" on "test" ("first_name", "last_name") where ("first_name" = 'Igal' or "age" >= 18)`, parameters: [], @@ -1181,7 +1707,7 @@ for (const dialect of DIALECTS) { it('should drop an index', async () => { let builder = ctx.db.schema.dropIndex('test_first_name_index') - if (dialect === 'mysql') { + if (dialect === 'mysql' || dialect === 'mssql') { builder = builder.on('test') } @@ -1194,6 +1720,10 @@ for (const dialect of DIALECTS) { sql: 'drop index `test_first_name_index` on `test`', parameters: [], }, + mssql: { + sql: 'drop index "test_first_name_index" on "test"', + parameters: [], + }, sqlite: { sql: 'drop index "test_first_name_index"', parameters: [], @@ -1203,22 +1733,34 @@ for (const dialect of DIALECTS) { await builder.execute() }) - if (dialect !== 'mysql') { + if ( + dialect === 'postgres' || + dialect === 'mssql' || + dialect === 'sqlite' + ) { it('should drop an index if it exists', async () => { let builder = ctx.db.schema .dropIndex('test_first_name_index') .ifExists() + if (dialect === 'mssql') { + builder = builder.on('test') + } + testSql(builder, dialect, { postgres: { sql: 'drop index if exists "test_first_name_index"', parameters: [], }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'drop index if exists "test_first_name_index" on "test"', + parameters: [], + }, sqlite: { sql: 'drop index if exists "test_first_name_index"', parameters: [], }, - mysql: NOT_SUPPORTED, }) await builder.execute() @@ -1237,6 +1779,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -1255,6 +1798,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -1281,6 +1825,10 @@ for (const dialect of DIALECTS) { sql: "create view `dogs` as select * from `pet` where `species` = 'dog'", parameters: [], }, + mssql: { + sql: `create view "dogs" as select * from "pet" where "species" = 'dog'`, + parameters: [], + }, sqlite: { sql: `create view "dogs" as select * from "pet" where "species" = 'dog'`, parameters: [], @@ -1290,13 +1838,13 @@ for (const dialect of DIALECTS) { await builder.execute() }) - if (dialect !== 'mysql') { + if (dialect === 'postgres' || dialect === 'sqlite') { it('should create a temporary view', async () => { const builder = ctx.db.schema .createView('dogs') .temporary() .as( - ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog') + ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog'), ) testSql(builder, dialect, { @@ -1304,24 +1852,25 @@ for (const dialect of DIALECTS) { sql: `create temporary view "dogs" as select * from "pet" where "species" = 'dog'`, parameters: [], }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: `create temporary view "dogs" as select * from "pet" where "species" = 'dog'`, parameters: [], }, - mysql: NOT_SUPPORTED, }) await builder.execute() }) } - if (dialect !== 'sqlite') { + if (dialect === 'postgres' || dialect === 'mysql') { it('should create or replace a view', async () => { const builder = ctx.db.schema .createView('dogs') .orReplace() .as( - ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog') + ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog'), ) testSql(builder, dialect, { @@ -1333,6 +1882,7 @@ for (const dialect of DIALECTS) { sql: "create or replace view `dogs` as select * from `pet` where `species` = 'dog'", parameters: [], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -1346,16 +1896,17 @@ for (const dialect of DIALECTS) { .createView('dogs') .ifNotExists() .as( - ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog') + ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog'), ) testSql(builder, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: `create view if not exists "dogs" as select * from "pet" where "species" = 'dog'`, parameters: [], }, - postgres: NOT_SUPPORTED, - mysql: NOT_SUPPORTED, }) await builder.execute() @@ -1368,7 +1919,7 @@ for (const dialect of DIALECTS) { .createView('materialized_dogs') .materialized() .as( - ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog') + ctx.db.selectFrom('pet').selectAll().where('species', '=', 'dog'), ) testSql(builder, dialect, { @@ -1377,6 +1928,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -1421,6 +1973,10 @@ for (const dialect of DIALECTS) { sql: 'drop view `dogs`', parameters: [], }, + mssql: { + sql: `drop view "dogs"`, + parameters: [], + }, sqlite: { sql: `drop view "dogs"`, parameters: [], @@ -1442,6 +1998,10 @@ for (const dialect of DIALECTS) { sql: 'drop view if exists `dogs`', parameters: [], }, + mssql: { + sql: `drop view if exists "dogs"`, + parameters: [], + }, sqlite: { sql: `drop view if exists "dogs"`, parameters: [], @@ -1450,7 +2010,8 @@ for (const dialect of DIALECTS) { await builder.execute() }) - if (dialect !== 'sqlite') { + + if (dialect === 'postgres' || dialect === 'mysql') { it('should drop a view cascade', async () => { const builder = ctx.db.schema.dropView('dogs').cascade() @@ -1463,11 +2024,13 @@ for (const dialect of DIALECTS) { sql: 'drop view `dogs` cascade', parameters: [], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) await builder.execute() }) + it('should drop a view cascade if it exists', async () => { const builder = ctx.db.schema.dropView('dogs').ifExists().cascade() @@ -1480,6 +2043,7 @@ for (const dialect of DIALECTS) { sql: 'drop view if exists `dogs` cascade', parameters: [], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -1489,10 +2053,14 @@ for (const dialect of DIALECTS) { }) describe('create schema', () => { - if (dialect === 'postgres' || dialect === 'mysql') { - beforeEach(cleanup) - afterEach(cleanup) + beforeEach(cleanup) + afterEach(cleanup) + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'mssql' + ) { it('should create a schema', async () => { const builder = ctx.db.schema.createSchema('pets') @@ -1505,12 +2073,18 @@ for (const dialect of DIALECTS) { sql: 'create schema `pets`', parameters: [], }, + mssql: { + sql: `create schema "pets"`, + parameters: [], + }, sqlite: NOT_SUPPORTED, }) await builder.execute() }) + } + if (dialect === 'postgres' || dialect === 'mysql') { it('should create a schema if not exists', async () => { const builder = ctx.db.schema.createSchema('pets').ifNotExists() @@ -1523,6 +2097,7 @@ for (const dialect of DIALECTS) { sql: 'create schema if not exists `pets`', parameters: [], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -1536,10 +2111,14 @@ for (const dialect of DIALECTS) { }) describe('drop schema', () => { - if (dialect === 'postgres' || dialect === 'mysql') { - beforeEach(cleanup) - afterEach(cleanup) + beforeEach(cleanup) + afterEach(cleanup) + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'mssql' + ) { it('should drop a schema', async () => { await ctx.db.schema.createSchema('pets').execute() @@ -1554,6 +2133,10 @@ for (const dialect of DIALECTS) { sql: 'drop schema `pets`', parameters: [], }, + mssql: { + sql: `drop schema "pets"`, + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -1572,46 +2155,50 @@ for (const dialect of DIALECTS) { sql: 'drop schema if exists `pets`', parameters: [], }, + mssql: { + sql: `drop schema if exists "pets"`, + parameters: [], + }, sqlite: NOT_SUPPORTED, }) await builder.execute() }) - if (dialect === 'postgres') { - it('should drop a schema cascade', async () => { - await ctx.db.schema.createSchema('pets').execute() - const builder = ctx.db.schema.dropSchema('pets').cascade() + } - testSql(builder, dialect, { - postgres: { - sql: `drop schema "pets" cascade`, - parameters: [], - }, - mysql: NOT_SUPPORTED, - sqlite: NOT_SUPPORTED, - }) + if (dialect === 'postgres') { + it('should drop a schema cascade', async () => { + await ctx.db.schema.createSchema('pets').execute() + const builder = ctx.db.schema.dropSchema('pets').cascade() - await builder.execute() + testSql(builder, dialect, { + postgres: { + sql: `drop schema "pets" cascade`, + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, }) - it('should drop a schema cascade if exists', async () => { - const builder = ctx.db.schema - .dropSchema('pets') - .cascade() - .ifExists() + await builder.execute() + }) - testSql(builder, dialect, { - postgres: { - sql: `drop schema if exists "pets" cascade`, - parameters: [], - }, - mysql: NOT_SUPPORTED, - sqlite: NOT_SUPPORTED, - }) + it('should drop a schema cascade if exists', async () => { + const builder = ctx.db.schema.dropSchema('pets').cascade().ifExists() - await builder.execute() + testSql(builder, dialect, { + postgres: { + sql: `drop schema if exists "pets" cascade`, + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, }) - } + + await builder.execute() + }) } async function cleanup() { @@ -1635,6 +2222,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -1663,6 +2251,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -1678,6 +2267,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -1703,38 +2293,71 @@ for (const dialect of DIALECTS) { it('should add a column', async () => { const builder = ctx.db.schema .alterTable('test') - .addColumn('bool_col', 'boolean', (cb) => cb.notNull()) + .addColumn('date_col', 'date', (cb) => cb.notNull()) testSql(builder, dialect, { postgres: { - sql: 'alter table "test" add column "bool_col" boolean not null', + sql: 'alter table "test" add column "date_col" date not null', parameters: [], }, mysql: { - sql: 'alter table `test` add column `bool_col` boolean not null', + sql: 'alter table `test` add column `date_col` date not null', + parameters: [], + }, + mssql: { + sql: 'alter table "test" add "date_col" date not null', parameters: [], }, sqlite: { - sql: 'alter table "test" add column "bool_col" boolean not null', + sql: 'alter table "test" add column "date_col" date not null', parameters: [], }, }) await builder.execute() + }) - expect(await getColumnMeta('test.bool_col')).to.containSubset({ - name: 'bool_col', - isNullable: false, - dataType: - dialect === 'postgres' - ? 'bool' - : dialect === 'sqlite' - ? 'boolean' - : 'tinyint', + if (dialect === 'postgres') { + it('should add a column with "unique nulls not distinct" modifier', async () => { + const builder = ctx.db.schema + .alterTable('test') + .addColumn('desc', 'varchar(20)', (cb) => + cb.unique().nullsNotDistinct(), + ) + + testSql(builder, dialect, { + postgres: { + sql: 'alter table "test" add column "desc" varchar(20) unique nulls not distinct', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() }) - }) - if (dialect !== 'sqlite') { + it('should add a column with "if not exists" modifier', async () => { + const builder = ctx.db.schema + .alterTable('test') + .addColumn('desc', 'varchar(20)', (cb) => cb.ifNotExists()) + + testSql(builder, dialect, { + postgres: { + sql: 'alter table "test" add column if not exists "desc" varchar(20)', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + } + + if (dialect === 'postgres' || dialect === 'mysql') { it('should add a unique column', async () => { const builder = ctx.db.schema .alterTable('test') @@ -1749,10 +2372,8 @@ for (const dialect of DIALECTS) { sql: 'alter table `test` add column `bool_col` boolean not null unique', parameters: [], }, - sqlite: { - sql: 'alter table "test" add column "bool_col" boolean not null unique', - parameters: [], - }, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, }) await builder.execute() @@ -1763,7 +2384,13 @@ for (const dialect of DIALECTS) { dataType: dialect === 'postgres' ? 'bool' : 'tinyint', }) }) + } + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'mssql' + ) { it('should add multiple columns', async () => { const builder = ctx.db.schema .alterTable('test') @@ -1787,14 +2414,15 @@ for (const dialect of DIALECTS) { ], parameters: [], }, - sqlite: { + mssql: { sql: [ 'alter table "test"', - 'add column "another_col" text,', - 'add column "yet_another_col" integer', + 'add "another_col" text,', + '"yet_another_col" integer', ], parameters: [], }, + sqlite: NOT_SUPPORTED, }) await builder.execute() @@ -1810,11 +2438,12 @@ for (const dialect of DIALECTS) { .modifyColumn('varchar_col', 'text') testSql(builder, dialect, { + postgres: NOT_SUPPORTED, mysql: { sql: 'alter table `test` modify column `varchar_col` text', parameters: [], }, - postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -1832,6 +2461,7 @@ for (const dialect of DIALECTS) { parameters: [], }, postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -1845,7 +2475,7 @@ for (const dialect of DIALECTS) { .execute() expect( - (await getColumnMeta('test.varchar_col')).isNullable + (await getColumnMeta('test.varchar_col')).isNullable, ).to.equal(false) const builder = ctx.db.schema @@ -1858,13 +2488,14 @@ for (const dialect of DIALECTS) { parameters: [], }, postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) await builder.execute() expect( - (await getColumnMeta('test.varchar_col')).isNullable + (await getColumnMeta('test.varchar_col')).isNullable, ).to.equal(true) }) @@ -1884,6 +2515,7 @@ for (const dialect of DIALECTS) { parameters: [], }, postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -1892,110 +2524,120 @@ for (const dialect of DIALECTS) { }) } - if (dialect !== 'sqlite') { + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'mssql' + ) { describe('alter column', () => { - it('should set default value', async () => { - const builder = ctx.db.schema - .alterTable('test') - .alterColumn('varchar_col', (ac) => ac.setDefault('foo')) - - testSql(builder, dialect, { - postgres: { - sql: `alter table "test" alter column "varchar_col" set default 'foo'`, - parameters: [], - }, - mysql: { - sql: "alter table `test` alter column `varchar_col` set default 'foo'", - parameters: [], - }, - sqlite: NOT_SUPPORTED, - }) - - await builder.execute() - }) - - it('should drop default value', async () => { - const subject = 'varchar_col' - - await ctx.db.schema - .alterTable('test') - .alterColumn(subject, (ac) => ac.setDefault('foo')) - .execute() - - const builder = ctx.db.schema - .alterTable('test') - .alterColumn(subject, (ac) => ac.dropDefault()) - - testSql(builder, dialect, { - postgres: { - sql: 'alter table "test" alter column "varchar_col" drop default', - parameters: [], - }, - mysql: { - sql: 'alter table `test` alter column `varchar_col` drop default', - parameters: [], - }, - sqlite: NOT_SUPPORTED, - }) - await builder.execute() - }) - - if (dialect !== 'mysql') { - it('should set column data type', async () => { + if (dialect === 'postgres' || dialect === 'mysql') { + it('should set default value', async () => { const builder = ctx.db.schema .alterTable('test') - .alterColumn('varchar_col', (ac) => ac.setDataType('text')) + .alterColumn('varchar_col', (ac) => ac.setDefault('foo')) testSql(builder, dialect, { postgres: { - sql: 'alter table "test" alter column "varchar_col" type text', + sql: `alter table "test" alter column "varchar_col" set default 'foo'`, parameters: [], }, - sqlite: { - sql: 'alter table "test" alter column "varchar_col" type text', + mysql: { + sql: "alter table `test` alter column `varchar_col` set default 'foo'", parameters: [], }, - mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, }) await builder.execute() }) - it('should set column data type from expression', async () => { + it('should drop default value', async () => { + const subject = 'varchar_col' + + await ctx.db.schema + .alterTable('test') + .alterColumn(subject, (ac) => ac.setDefault('foo')) + .execute() + const builder = ctx.db.schema .alterTable('test') - .alterColumn('varchar_col', (ac) => ac.setDataType(sql`text`)) + .alterColumn(subject, (ac) => ac.dropDefault()) testSql(builder, dialect, { postgres: { - sql: 'alter table "test" alter column "varchar_col" type text', + sql: 'alter table "test" alter column "varchar_col" drop default', parameters: [], }, - sqlite: { - sql: 'alter table "test" alter column "varchar_col" type text', + mysql: { + sql: 'alter table `test` alter column `varchar_col` drop default', parameters: [], }, - mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, }) - await builder.execute() }) + } - it('should add not null constraint for column', async () => { + if (dialect === 'postgres' || dialect === 'mssql') { + it('should set column data type', async () => { const builder = ctx.db.schema .alterTable('test') - .alterColumn('varchar_col', (ac) => ac.setNotNull()) + .alterColumn('varchar_col', (ac) => ac.setDataType('text')) testSql(builder, dialect, { postgres: { - sql: 'alter table "test" alter column "varchar_col" set not null', + sql: 'alter table "test" alter column "varchar_col" type text', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'alter table "test" alter column "varchar_col" text', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + + it('should set column data type from expression', async () => { + const builder = ctx.db.schema + .alterTable('test') + .alterColumn('varchar_col', (ac) => ac.setDataType(sql`text`)) + + testSql(builder, dialect, { + postgres: { + sql: 'alter table "test" alter column "varchar_col" type text', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'alter table "test" alter column "varchar_col" text', parameters: [], }, - sqlite: { + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + } + + if (dialect === 'postgres') { + it('should add not null constraint for column', async () => { + const builder = ctx.db.schema + .alterTable('test') + .alterColumn('varchar_col', (ac) => ac.setNotNull()) + + testSql(builder, dialect, { + postgres: { sql: 'alter table "test" alter column "varchar_col" set not null', parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, }) await builder.execute() @@ -2016,45 +2658,46 @@ for (const dialect of DIALECTS) { sql: 'alter table "test" alter column "varchar_col" drop not null', parameters: [], }, - sqlite: { - sql: 'alter table "test" alter column "varchar_col" drop not null', - parameters: [], - }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, }) await builder.execute() }) } - it('should alter multiple columns', async () => { - const builder = ctx.db.schema - .alterTable('test') - .alterColumn('varchar_col', (ac) => ac.setDefault('foo')) - .alterColumn('integer_col', (ac) => ac.setDefault(5)) + if (dialect === 'postgres' || dialect === 'mysql') { + it('should alter multiple columns', async () => { + const builder = ctx.db.schema + .alterTable('test') + .alterColumn('varchar_col', (ac) => ac.setDefault('foo')) + .alterColumn('integer_col', (ac) => ac.setDefault(5)) - testSql(builder, dialect, { - postgres: { - sql: [ - `alter table "test"`, - `alter column "varchar_col" set default 'foo',`, - `alter column "integer_col" set default 5`, - ], - parameters: [], - }, - mysql: { - sql: [ - 'alter table `test`', - "alter column `varchar_col` set default 'foo',", - 'alter column `integer_col` set default 5', - ], - parameters: [], - }, - sqlite: NOT_SUPPORTED, - }) + testSql(builder, dialect, { + postgres: { + sql: [ + `alter table "test"`, + `alter column "varchar_col" set default 'foo',`, + `alter column "integer_col" set default 5`, + ], + parameters: [], + }, + mysql: { + sql: [ + 'alter table `test`', + "alter column `varchar_col` set default 'foo',", + 'alter column `integer_col` set default 5', + ], + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) - await builder.execute() - }) + await builder.execute() + }) + } }) } @@ -2073,6 +2716,10 @@ for (const dialect of DIALECTS) { sql: 'alter table `test` drop column `varchar_col`', parameters: [], }, + mssql: { + sql: 'alter table "test" drop column "varchar_col"', + parameters: [], + }, sqlite: { sql: 'alter table "test" drop column "varchar_col"', parameters: [], @@ -2082,7 +2729,11 @@ for (const dialect of DIALECTS) { await builder.execute() }) - if (dialect !== 'sqlite') { + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'mssql' + ) { it('should drop multiple columns', async () => { await ctx.db.schema .alterTable('test') @@ -2111,6 +2762,14 @@ for (const dialect of DIALECTS) { ], parameters: [], }, + mssql: { + sql: [ + 'alter table "test"', + 'drop column "varchar_col",', + '"text_col"', + ], + parameters: [], + }, sqlite: { sql: [ 'alter table "test"', @@ -2126,28 +2785,35 @@ for (const dialect of DIALECTS) { } }) - describe('rename', () => { - it('should rename a table', async () => { - const builder = ctx.db.schema.alterTable('test').renameTo('test2') + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'sqlite' + ) { + describe('rename', () => { + it('should rename a table', async () => { + const builder = ctx.db.schema.alterTable('test').renameTo('test2') - testSql(builder, dialect, { - postgres: { - sql: 'alter table "test" rename to "test2"', - parameters: [], - }, - mysql: { - sql: 'alter table `test` rename to `test2`', - parameters: [], - }, - sqlite: { - sql: 'alter table "test" rename to "test2"', - parameters: [], - }, - }) + testSql(builder, dialect, { + postgres: { + sql: 'alter table "test" rename to "test2"', + parameters: [], + }, + mysql: { + sql: 'alter table `test` rename to `test2`', + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'alter table "test" rename to "test2"', + parameters: [], + }, + }) - await builder.execute() + await builder.execute() + }) }) - }) + } if (dialect === 'postgres') { describe('set schema', () => { @@ -2160,6 +2826,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -2168,134 +2835,136 @@ for (const dialect of DIALECTS) { }) } - describe('rename column', () => { - it('should rename a column', async () => { - const builder = ctx.db.schema - .alterTable('test') - .renameColumn('varchar_col', 'text_col') - - testSql(builder, dialect, { - postgres: { - sql: 'alter table "test" rename column "varchar_col" to "text_col"', - parameters: [], - }, - mysql: { - sql: 'alter table `test` rename column `varchar_col` to `text_col`', - parameters: [], - }, - sqlite: { - sql: 'alter table "test" rename column "varchar_col" to "text_col"', - parameters: [], - }, - }) - - await builder.execute() - }) - - if (dialect === 'mysql') { - it('should rename multiple columns', async () => { + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'sqlite' + ) { + describe('rename column', () => { + it('should rename a column', async () => { const builder = ctx.db.schema .alterTable('test') .renameColumn('varchar_col', 'text_col') - .renameColumn('integer_col', 'number_col') testSql(builder, dialect, { postgres: { - sql: [ - 'alter table "test"', - 'rename column "varchar_col" to "text_col",', - 'rename column "integer_col" to "number_col"', - ], + sql: 'alter table "test" rename column "varchar_col" to "text_col"', parameters: [], }, mysql: { - sql: [ - 'alter table `test`', - 'rename column `varchar_col` to `text_col`,', - 'rename column `integer_col` to `number_col`', - ], + sql: 'alter table `test` rename column `varchar_col` to `text_col`', parameters: [], }, + mssql: NOT_SUPPORTED, sqlite: { - sql: [ - 'alter table "test"', - 'rename column "varchar_col" to "text_col",', - 'rename column "integer_col" to "number_col"', - ], + sql: 'alter table "test" rename column "varchar_col" to "text_col"', parameters: [], }, }) await builder.execute() }) - } - }) - describe('mixed column alterations', () => { - if (dialect === 'postgres') { - it('should alter multiple columns in various ways', async () => { - const builder = ctx.db.schema - .alterTable('test') - .addColumn('another_varchar_col', 'varchar(255)') - .alterColumn('varchar_col', (ac) => ac.setDefault('foo')) - .dropColumn('integer_col') + if (dialect === 'mysql') { + it('should rename multiple columns', async () => { + const builder = ctx.db.schema + .alterTable('test') + .renameColumn('varchar_col', 'text_col') + .renameColumn('integer_col', 'number_col') - testSql(builder, dialect, { - postgres: { - sql: [ - `alter table "test"`, - `add column "another_varchar_col" varchar(255),`, - `alter column "varchar_col" set default 'foo',`, - `drop column "integer_col"`, - ], - parameters: [], - }, - mysql: NOT_SUPPORTED, - sqlite: NOT_SUPPORTED, - }) + testSql(builder, dialect, { + postgres: NOT_SUPPORTED, + mysql: { + sql: [ + 'alter table `test`', + 'rename column `varchar_col` to `text_col`,', + 'rename column `integer_col` to `number_col`', + ], + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) - await builder.execute() - }) - } + await builder.execute() + }) + } + }) + } - if (dialect === 'mysql') { - it('should alter multiple columns in various ways', async () => { - await ctx.db.schema - .alterTable('test') - .addColumn('rename_me', 'text') - .addColumn('modify_me', 'boolean') - .execute() + if (dialect === 'postgres' || dialect === 'mysql') { + describe('mixed column alterations', () => { + if (dialect === 'postgres') { + it('should alter multiple columns in various ways', async () => { + const builder = ctx.db.schema + .alterTable('test') + .addColumn('another_varchar_col', 'varchar(255)') + .alterColumn('varchar_col', (ac) => ac.setDefault('foo')) + .dropColumn('integer_col') - const builder = ctx.db.schema - .alterTable('test') - .addColumn('another_varchar_col', 'varchar(255)') - .alterColumn('varchar_col', (ac) => ac.setDefault('foo')) - .dropColumn('integer_col') - .renameColumn('rename_me', 'text_col') - .modifyColumn('modify_me', 'bigint') + testSql(builder, dialect, { + postgres: { + sql: [ + `alter table "test"`, + `add column "another_varchar_col" varchar(255),`, + `alter column "varchar_col" set default 'foo',`, + `drop column "integer_col"`, + ], + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) - testSql(builder, dialect, { - postgres: NOT_SUPPORTED, - mysql: { - sql: [ - 'alter table `test`', - 'add column `another_varchar_col` varchar(255),', - "alter column `varchar_col` set default 'foo',", - 'drop column `integer_col`,', - 'rename column `rename_me` to `text_col`,', - 'modify column `modify_me` bigint', - ], - parameters: [], - }, - sqlite: NOT_SUPPORTED, + await builder.execute() }) + } - await builder.execute() - }) - } - }) + if (dialect === 'mysql') { + it('should alter multiple columns in various ways', async () => { + await ctx.db.schema + .alterTable('test') + .addColumn('rename_me', 'text') + .addColumn('modify_me', 'boolean') + .execute() - if (dialect !== 'sqlite') { + const builder = ctx.db.schema + .alterTable('test') + .addColumn('another_varchar_col', 'varchar(255)') + .alterColumn('varchar_col', (ac) => ac.setDefault('foo')) + .dropColumn('integer_col') + .renameColumn('rename_me', 'text_col') + .modifyColumn('modify_me', 'bigint') + + testSql(builder, dialect, { + postgres: NOT_SUPPORTED, + mysql: { + sql: [ + 'alter table `test`', + 'add column `another_varchar_col` varchar(255),', + "alter column `varchar_col` set default 'foo',", + 'drop column `integer_col`,', + 'rename column `rename_me` to `text_col`,', + 'modify column `modify_me` bigint', + ], + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + } + }) + } + + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'mssql' + ) { describe('add unique constraint', () => { it('should add a unique constraint', async () => { const builder = ctx.db.schema @@ -2314,6 +2983,10 @@ for (const dialect of DIALECTS) { sql: 'alter table `test` add constraint `some_constraint` unique (`varchar_col`, `integer_col`)', parameters: [], }, + mssql: { + sql: 'alter table "test" add constraint "some_constraint" unique ("varchar_col", "integer_col")', + parameters: [], + }, sqlite: { sql: 'alter table "test" add constraint "some_constraint" unique ("varchar_col", "integer_col")', parameters: [], @@ -2322,10 +2995,38 @@ for (const dialect of DIALECTS) { await builder.execute() }) + + if (dialect === 'postgres') { + it('should add a unique constraint with "nulls not distinct" modifier', async () => { + const builder = ctx.db.schema + .alterTable('test') + .addUniqueConstraint( + 'varchar_col_constaint', + ['varchar_col'], + (builder) => builder.nullsNotDistinct(), + ) + + testSql(builder, dialect, { + postgres: { + sql: 'alter table "test" add constraint "varchar_col_constaint" unique nulls not distinct ("varchar_col")', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + } }) } - if (dialect !== 'sqlite') { + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'mssql' + ) { describe('add check constraint', () => { it('should add a check constraint', async () => { const builder = ctx.db.schema @@ -2341,6 +3042,10 @@ for (const dialect of DIALECTS) { sql: 'alter table `test` add constraint `some_constraint` check (integer_col > 0)', parameters: [], }, + mssql: { + sql: 'alter table "test" add constraint "some_constraint" check (integer_col > 0)', + parameters: [], + }, sqlite: { sql: 'alter table "test" add constraint "some_constraint" check (integer_col > 0)', parameters: [], @@ -2352,7 +3057,11 @@ for (const dialect of DIALECTS) { }) } - if (dialect !== 'sqlite') { + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'mssql' + ) { describe('add foreign key constraint', () => { it('should add a foreign key constraint', async () => { await ctx.db.schema @@ -2368,7 +3077,7 @@ for (const dialect of DIALECTS) { 'some_constraint', ['integer_col', 'varchar_col'], 'test2', - ['a', 'b'] + ['a', 'b'], ) testSql(builder, dialect, { @@ -2380,10 +3089,11 @@ for (const dialect of DIALECTS) { sql: 'alter table `test` add constraint `some_constraint` foreign key (`integer_col`, `varchar_col`) references `test2` (`a`, `b`)', parameters: [], }, - sqlite: { + mssql: { sql: 'alter table "test" add constraint "some_constraint" foreign key ("integer_col", "varchar_col") references "test2" ("a", "b")', parameters: [], }, + sqlite: NOT_SUPPORTED, }) await builder.execute() @@ -2403,7 +3113,7 @@ for (const dialect of DIALECTS) { 'some_constraint', ['integer_col', 'varchar_col'], 'test2', - ['a', 'b'] + ['a', 'b'], ) .onDelete('set null') .onUpdate('cascade') @@ -2417,10 +3127,11 @@ for (const dialect of DIALECTS) { sql: 'alter table `test` add constraint `some_constraint` foreign key (`integer_col`, `varchar_col`) references `test2` (`a`, `b`) on delete set null on update cascade', parameters: [], }, - sqlite: { + mssql: { sql: 'alter table "test" add constraint "some_constraint" foreign key ("integer_col", "varchar_col") references "test2" ("a", "b") on delete set null on update cascade', parameters: [], }, + sqlite: NOT_SUPPORTED, }) await builder.execute() @@ -2443,7 +3154,7 @@ for (const dialect of DIALECTS) { 'foreign_key_constraint', ['foreign_key'], 'test2', - ['id'] + ['id'], ) .execute() @@ -2460,6 +3171,10 @@ for (const dialect of DIALECTS) { sql: 'alter table `test` drop constraint `foreign_key_constraint`', parameters: [], }, + mssql: { + sql: 'alter table "test" drop constraint "foreign_key_constraint"', + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -2468,14 +3183,103 @@ for (const dialect of DIALECTS) { }) } - if (dialect !== 'sqlite') { + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'mssql' + ) { + describe('add primary key constraint', async () => { + beforeEach(() => { + return ctx.db.schema + .alterTable('test') + .addColumn('decimal_col', 'decimal', (cb) => cb.notNull()) + .addColumn('smallint_col', sql`smallint`, (cb) => cb.notNull()) + .execute() + }) + + afterEach(async () => { + if (dialect === 'mssql') { + await ctx.db.schema + .alterTable('test') + .dropConstraint('test_pkey') + .execute() + } + + await ctx.db.schema + .alterTable('test') + .dropColumn('decimal_col') + .dropColumn('smallint_col') + .execute() + }) + + it('should add a primary key constraint', async () => { + const builder = ctx.db.schema + .alterTable('test') + .addPrimaryKeyConstraint('test_pkey', ['decimal_col']) + + testSql(builder, dialect, { + postgres: { + sql: 'alter table "test" add constraint "test_pkey" primary key ("decimal_col")', + parameters: [], + }, + mysql: { + sql: 'alter table `test` add constraint `test_pkey` primary key (`decimal_col`)', + parameters: [], + }, + mssql: { + sql: 'alter table "test" add constraint "test_pkey" primary key ("decimal_col")', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + + it('should add a primary key constraint for multiple columns', async () => { + const builder = ctx.db.schema + .alterTable('test') + .addPrimaryKeyConstraint('test_pkey', [ + 'decimal_col', + 'smallint_col', + ]) + + testSql(builder, dialect, { + postgres: { + sql: 'alter table "test" add constraint "test_pkey" primary key ("decimal_col", "smallint_col")', + parameters: [], + }, + mysql: { + sql: 'alter table `test` add constraint `test_pkey` primary key (`decimal_col`, `smallint_col`)', + parameters: [], + }, + mssql: { + sql: 'alter table "test" add constraint "test_pkey" primary key ("decimal_col", "smallint_col")', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + await builder.execute() + }) + }) + } + + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'mssql' + ) { describe('parse schema name', () => { beforeEach(cleanup) afterEach(cleanup) it('should parse the schema from table name', async () => { - await ctx.db.schema.createSchema('test_schema').ifNotExists().execute() - await ctx.db.schema.createTable('test_schema.test').addColumn('id', 'serial').execute(); + await ctx.db.schema.createSchema('test_schema').execute() + await ctx.db.schema + .createTable('test_schema.test') + .addColumn('id', 'varchar(36)') + .execute() const builder = ctx.db.schema .alterTable('test_schema.test') @@ -2487,7 +3291,11 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: { - sql: "alter table `test_schema`.`test` add column `second_column` text", + sql: 'alter table `test_schema`.`test` add column `second_column` text', + parameters: [], + }, + mssql: { + sql: `alter table "test_schema"."test" add "second_column" text`, parameters: [], }, sqlite: NOT_SUPPORTED, @@ -2497,7 +3305,10 @@ for (const dialect of DIALECTS) { }) async function cleanup() { - await ctx.db.schema.dropTable('test_schema.test').ifExists().execute() + await ctx.db.schema + .dropTable('test_schema.test') + .ifExists() + .execute() await ctx.db.schema.dropSchema('test_schema').ifExists().execute() } }) @@ -2507,26 +3318,180 @@ for (const dialect of DIALECTS) { const builder = ctx.db.schema .alterTable('test') .$call((builder) => - builder.addColumn('abc', 'integer', (col) => col.defaultTo('42')) + builder.addColumn('abc', 'integer', (col) => col.notNull()), ) testSql(builder, dialect, { postgres: { - sql: [`alter table "test" add column "abc" integer default '42'`], + sql: [`alter table "test" add column "abc" integer not null`], parameters: [], }, mysql: { - sql: ["alter table `test` add column `abc` integer default '42'"], + sql: ['alter table `test` add column `abc` integer not null'], + parameters: [], + }, + mssql: { + sql: [`alter table "test" add "abc" integer not null`], parameters: [], }, sqlite: { - sql: [`alter table "test" add column "abc" integer default '42'`], + sql: [`alter table "test" add column "abc" integer not null`], parameters: [], }, }) await builder.execute() }) + + if (dialect === 'mysql') { + describe('add index', () => { + it('should add an index', async () => { + const query = ctx.db.schema + .alterTable('test') + .addIndex('test_integer_col_index') + .column('integer_col') + + testSql(query, dialect, { + mysql: { + sql: 'alter table `test` add index `test_integer_col_index` (`integer_col`)', + parameters: [], + }, + postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + + it('should add a unique index', async () => { + const query = ctx.db.schema + .alterTable('test') + .addIndex('test_integer_col_index') + .unique() + .column('integer_col') + + testSql(query, dialect, { + mysql: { + sql: 'alter table `test` add unique index `test_integer_col_index` (`integer_col`)', + parameters: [], + }, + postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + + it('should add an index for multiple columns', async () => { + const query = ctx.db.schema + .alterTable('test') + .addIndex('test_integer_varchar_col_index') + .unique() + .columns(['integer_col', 'varchar_col']) + + testSql(query, dialect, { + mysql: { + sql: 'alter table `test` add unique index `test_integer_varchar_col_index` (`integer_col`, `varchar_col`)', + parameters: [], + }, + postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + + it('should add an index for an expression', async () => { + const query = ctx.db.schema + .alterTable('test') + .addIndex('test_varchar_col_index') + .expression(sql`(varchar_col < 'Sami')`) + + testSql(query, dialect, { + mysql: { + sql: "alter table `test` add index `test_varchar_col_index` ((varchar_col < 'Sami'))", + parameters: [], + }, + postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + + it('should add a sorted index, single column', async () => { + const query = ctx.db.schema + .alterTable('test') + .addIndex('test_integer_col_index') + .column('integer_col desc') + + testSql(query, dialect, { + mysql: { + sql: 'alter table `test` add index `test_integer_col_index` (`integer_col` desc)', + parameters: [], + }, + postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + + it('should add a sorted index, multi-column', async () => { + const query = ctx.db.schema + .alterTable('test') + .addIndex('test_integer_varchar_col_index') + .columns(['integer_col desc', 'varchar_col desc']) + + testSql(query, dialect, { + mysql: { + sql: 'alter table `test` add index `test_integer_varchar_col_index` (`integer_col` desc, `varchar_col` desc)', + parameters: [], + }, + postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + }) + } + + if (dialect === 'mysql') { + describe('drop index', () => { + beforeEach(async () => { + await ctx.db.schema + .alterTable('test') + .addIndex('test_integer_col_index') + .column('integer_col') + .execute() + }) + + it('should drop an index', async () => { + const query = ctx.db.schema + .alterTable('test') + .dropIndex('test_integer_col_index') + + testSql(query, dialect, { + mysql: { + sql: 'alter table `test` drop index `test_integer_col_index`', + parameters: [], + }, + postgres: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + }) + } }) async function dropTestTables(): Promise { diff --git a/test/node/src/select.test.ts b/test/node/src/select.test.ts index d9d1c5f3a..00477a19d 100644 --- a/test/node/src/select.test.ts +++ b/test/node/src/select.test.ts @@ -2,7 +2,6 @@ import { Kysely, PostgresDialect, sql } from '../../../' import { Pool } from 'pg' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -15,6 +14,8 @@ import { DIALECT_CONFIGS, Database, POOL_SIZE, + DIALECTS, + limit, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -77,6 +78,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where `first_name` = ?', parameters: ['Jennifer'], }, + mssql: { + sql: 'select * from "person" where "first_name" = @1', + parameters: ['Jennifer'], + }, sqlite: { sql: 'select * from "person" where "first_name" = ?', parameters: ['Jennifer'], @@ -106,6 +111,10 @@ for (const dialect of DIALECTS) { sql: 'select `person`.* from `person` where `first_name` = ?', parameters: ['Jennifer'], }, + mssql: { + sql: 'select "person".* from "person" where "first_name" = @1', + parameters: ['Jennifer'], + }, sqlite: { sql: 'select "person".* from "person" where "first_name" = ?', parameters: ['Jennifer'], @@ -120,7 +129,7 @@ for (const dialect of DIALECTS) { ]) }) - if (dialect === 'postgres') { + if (dialect === 'postgres' || dialect === 'mssql') { it('should select all columns of a table with a schema', async () => { const query = ctx.db .selectFrom('toy_schema.toy') @@ -132,6 +141,10 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'select "toy_schema"."toy".* from "toy_schema"."toy"', + parameters: [], + }, sqlite: NOT_SUPPORTED, }) }) @@ -152,6 +165,10 @@ for (const dialect of DIALECTS) { sql: 'select `last_name` from `person` where `first_name` = ?', parameters: ['Jennifer'], }, + mssql: { + sql: 'select "last_name" from "person" where "first_name" = @1', + parameters: ['Jennifer'], + }, sqlite: { sql: 'select "last_name" from "person" where "first_name" = ?', parameters: ['Jennifer'], @@ -179,6 +196,10 @@ for (const dialect of DIALECTS) { sql: 'select `last_name` as `ln` from `person` where `first_name` = ?', parameters: ['Jennifer'], }, + mssql: { + sql: 'select "last_name" as "ln" from "person" where "first_name" = @1', + parameters: ['Jennifer'], + }, sqlite: { sql: 'select "last_name" as "ln" from "person" where "first_name" = ?', parameters: ['Jennifer'], @@ -206,6 +227,10 @@ for (const dialect of DIALECTS) { sql: 'select `person`.`last_name` from `person` where `first_name` = ?', parameters: ['Jennifer'], }, + mssql: { + sql: 'select "person"."last_name" from "person" where "first_name" = @1', + parameters: ['Jennifer'], + }, sqlite: { sql: 'select "person"."last_name" from "person" where "first_name" = ?', parameters: ['Jennifer'], @@ -233,6 +258,10 @@ for (const dialect of DIALECTS) { sql: 'select `person`.`last_name` as `ln` from `person` where `first_name` = ?', parameters: ['Jennifer'], }, + mssql: { + sql: 'select "person"."last_name" as "ln" from "person" where "first_name" = @1', + parameters: ['Jennifer'], + }, sqlite: { sql: 'select "person"."last_name" as "ln" from "person" where "first_name" = ?', parameters: ['Jennifer'], @@ -253,7 +282,7 @@ for (const dialect of DIALECTS) { .selectFrom('pet') .whereRef('person.id', '=', 'pet.owner_id') .select('name') - .as('pet_name') + .as('pet_name'), ) .where('first_name', '=', 'Jennifer') @@ -266,6 +295,10 @@ for (const dialect of DIALECTS) { sql: 'select (select `name` from `pet` where `person`.`id` = `pet`.`owner_id`) as `pet_name` from `person` where `first_name` = ?', parameters: ['Jennifer'], }, + mssql: { + sql: 'select (select "name" from "pet" where "person"."id" = "pet"."owner_id") as "pet_name" from "person" where "first_name" = @1', + parameters: ['Jennifer'], + }, sqlite: { sql: 'select (select "name" from "pet" where "person"."id" = "pet"."owner_id") as "pet_name" from "person" where "first_name" = ?', parameters: ['Jennifer'], @@ -284,21 +317,25 @@ for (const dialect of DIALECTS) { .select((eb) => eb.fn .count(eb.case().when('first_name', '=', 'Jennifer').then(1).end()) - .as('num_jennifers') + .as('num_jennifers'), ) testSql(query, dialect, { postgres: { - sql: 'select count(case when "first_name" = $1 then $2 end) as "num_jennifers" from "person"', - parameters: ['Jennifer', 1], + sql: 'select count(case when "first_name" = $1 then 1 end) as "num_jennifers" from "person"', + parameters: ['Jennifer'], }, mysql: { - sql: 'select count(case when `first_name` = ? then ? end) as `num_jennifers` from `person`', - parameters: ['Jennifer', 1], + sql: 'select count(case when `first_name` = ? then 1 end) as `num_jennifers` from `person`', + parameters: ['Jennifer'], + }, + mssql: { + sql: 'select count(case when "first_name" = @1 then 1 end) as "num_jennifers" from "person"', + parameters: ['Jennifer'], }, sqlite: { - sql: 'select count(case when "first_name" = ? then ? end) as "num_jennifers" from "person"', - parameters: ['Jennifer', 1], + sql: 'select count(case when "first_name" = ? then 1 end) as "num_jennifers" from "person"', + parameters: ['Jennifer'], }, }) @@ -312,51 +349,61 @@ for (const dialect of DIALECTS) { } }) - if (dialect === 'postgres') { - it('should select the count of jennifers using sum', async () => { - const query = ctx.db - .selectFrom('person') - .select((eb) => - eb.fn - .sum( - eb - .case() - .when('first_name', '=', 'Jennifer') - .then(sql.lit(1)) - .else(sql.lit(0)) - .end() - ) - .as('num_jennifers') - ) + it('should select the count of jennifers using sum', async () => { + const query = ctx.db + .selectFrom('person') + .select((eb) => + eb.fn + .sum( + eb + .case() + .when('first_name', '=', 'Jennifer') + .then(sql.lit(1)) + .else(sql.lit(0)) + .end(), + ) + .as('num_jennifers'), + ) - testSql(query, dialect, { - postgres: { - sql: 'select sum(case when "first_name" = $1 then 1 else 0 end) as "num_jennifers" from "person"', - parameters: ['Jennifer'], - }, - mysql: NOT_SUPPORTED, - sqlite: NOT_SUPPORTED, - }) + testSql(query, dialect, { + postgres: { + sql: 'select sum(case when "first_name" = $1 then 1 else 0 end) as "num_jennifers" from "person"', + parameters: ['Jennifer'], + }, + mysql: { + sql: 'select sum(case when `first_name` = ? then 1 else 0 end) as `num_jennifers` from `person`', + parameters: ['Jennifer'], + }, + mssql: { + sql: 'select sum(case when "first_name" = @1 then 1 else 0 end) as "num_jennifers" from "person"', + parameters: ['Jennifer'], + }, + sqlite: { + sql: 'select sum(case when "first_name" = ? then 1 else 0 end) as "num_jennifers" from "person"', + parameters: ['Jennifer'], + }, + }) - const counts = await query.execute() + const counts = await query.execute() - expect(counts).to.have.length(1) - expect(counts[0]).to.eql({ num_jennifers: '1' }) + expect(counts).to.have.length(1) + expect(counts[0]).to.eql({ + num_jennifers: dialect === 'postgres' || dialect === 'mysql' ? '1' : 1, }) - } + }) - // Raw exrpessions are of course supported on all dialects, but we use an - // expression that's only valid on postgres. - if (dialect === 'postgres') { + // Raw expressions are of course supported on all dialects, but we use an + // expression that's only valid on postgres or mssql. + if (dialect === 'postgres' || dialect === 'mssql') { it('should select one field using a raw expression', async () => { const query = ctx.db .selectFrom('person') .select( sql`concat(${sql.ref( - 'first_name' + 'first_name', )}, ' ', cast(${'Muriel'} as varchar), ' ', ${sql.ref( - 'last_name' - )})`.as('full_name_with_middle_name') + 'last_name', + )})`.as('full_name_with_middle_name'), ) .where('first_name', '=', 'Jennifer') @@ -366,6 +413,10 @@ for (const dialect of DIALECTS) { parameters: ['Muriel', 'Jennifer'], }, mysql: NOT_SUPPORTED, + mssql: { + sql: `select concat("first_name", ' ', cast(@1 as varchar), ' ', "last_name") as "full_name_with_middle_name" from "person" where "first_name" = @2`, + parameters: ['Muriel', 'Jennifer'], + }, sqlite: NOT_SUPPORTED, }) @@ -380,7 +431,7 @@ for (const dialect of DIALECTS) { it('should select multiple fields', async () => { const fullName = - dialect === 'mysql' + dialect === 'mysql' || dialect === 'mssql' ? sql`concat(first_name, ' ', last_name)` : sql`first_name || ' ' || last_name` @@ -410,6 +461,10 @@ for (const dialect of DIALECTS) { sql: "select `first_name`, `last_name` as `ln`, `person`.`gender`, `person`.`first_name` as `fn`, concat(first_name, ' ', last_name) as `full_name`, (select `name` from `pet` where `person`.`id` = `owner_id`) as `pet_name` from `person` where `first_name` = ?", parameters: ['Jennifer'], }, + mssql: { + sql: `select "first_name", "last_name" as "ln", "person"."gender", "person"."first_name" as "fn", concat(first_name, ' ', last_name) as "full_name", (select "name" from "pet" where "person"."id" = "owner_id") as "pet_name" from "person" where "first_name" = @1`, + parameters: ['Jennifer'], + }, sqlite: { sql: `select "first_name", "last_name" as "ln", "person"."gender", "person"."first_name" as "fn", first_name || ' ' || last_name as "full_name", (select "name" from "pet" where "person"."id" = "owner_id") as "pet_name" from "person" where "first_name" = ?`, parameters: ['Jennifer'], @@ -447,6 +502,10 @@ for (const dialect of DIALECTS) { sql: 'select `last_name`, `name` as `pet_name` from `person`, `pet` where `owner_id` = `person`.`id` and `first_name` = ?', parameters: ['Jennifer'], }, + mssql: { + sql: 'select "last_name", "name" as "pet_name" from "person", "pet" where "owner_id" = "person"."id" and "first_name" = @1', + parameters: ['Jennifer'], + }, sqlite: { sql: 'select "last_name", "name" as "pet_name" from "person", "pet" where "owner_id" = "person"."id" and "first_name" = ?', parameters: ['Jennifer'], @@ -479,6 +538,10 @@ for (const dialect of DIALECTS) { sql: 'select `last_name`, `species` as `pet_species`, `one` from `person`, (select `owner_id`, `species` from `pet`) as `p`, (select 1 as one) as `o` where `p`.`owner_id` = `person`.`id` and `first_name` = ?', parameters: ['Jennifer'], }, + mssql: { + sql: 'select "last_name", "species" as "pet_species", "one" from "person", (select "owner_id", "species" from "pet") as "p", (select 1 as one) as "o" where "p"."owner_id" = "person"."id" and "first_name" = @1', + parameters: ['Jennifer'], + }, sqlite: { sql: 'select "last_name", "species" as "pet_species", "one" from "person", (select "owner_id", "species" from "pet") as "p", (select 1 as one) as "o" where "p"."owner_id" = "person"."id" and "first_name" = ?', parameters: ['Jennifer'], @@ -505,6 +568,10 @@ for (const dialect of DIALECTS) { sql: 'select `first_name`, `pet`.`name` as `pet_name`, `toy`.`name` as `toy_name` from `person` inner join `pet` on `owner_id` = `person`.`id` inner join `toy` on `pet_id` = `pet`.`id` where `first_name` = ?', parameters: ['Jennifer'], }, + mssql: { + sql: 'select "first_name", "pet"."name" as "pet_name", "toy"."name" as "toy_name" from "person" inner join "pet" on "owner_id" = "person"."id" inner join "toy" on "pet_id" = "pet"."id" where "first_name" = @1', + parameters: ['Jennifer'], + }, sqlite: { sql: 'select "first_name", "pet"."name" as "pet_name", "toy"."name" as "toy_name" from "person" inner join "pet" on "owner_id" = "person"."id" inner join "toy" on "pet_id" = "pet"."id" where "first_name" = ?', parameters: ['Jennifer'], @@ -535,6 +602,10 @@ for (const dialect of DIALECTS) { sql: 'select distinct `gender` from `person` order by `gender`', parameters: [], }, + mssql: { + sql: 'select distinct "gender" from "person" order by "gender"', + parameters: [], + }, sqlite: { sql: 'select distinct "gender" from "person" order by "gender"', parameters: [], @@ -547,7 +618,7 @@ for (const dialect of DIALECTS) { expect(persons).to.eql([{ gender: 'female' }, { gender: 'male' }]) }) - if (dialect !== 'sqlite') { + if (dialect === 'postgres' || dialect === 'mysql') { it('should select a row for update', async () => { const query = ctx.db .selectFrom('person') @@ -564,6 +635,114 @@ for (const dialect of DIALECTS) { sql: 'select `last_name` from `person` where `first_name` = ? for update', parameters: ['Jennifer'], }, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + const persons = await query.execute() + + expect(persons).to.have.length(1) + expect(persons).to.eql([{ last_name: 'Aniston' }]) + }) + + it('should select a row for update of', async () => { + const query = ctx.db + .selectFrom('person') + .select('last_name') + .where('first_name', '=', 'Jennifer') + .forUpdate('person') + + testSql(query, dialect, { + postgres: { + sql: 'select "last_name" from "person" where "first_name" = $1 for update of "person"', + parameters: ['Jennifer'], + }, + mysql: { + sql: 'select `last_name` from `person` where `first_name` = ? for update of `person`', + parameters: ['Jennifer'], + }, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + const persons = await query.execute() + + expect(persons).to.have.length(1) + expect(persons).to.eql([{ last_name: 'Aniston' }]) + }) + + it('should select a row for update with skip locked', async () => { + const query = ctx.db + .selectFrom('person') + .select('last_name') + .where('first_name', '=', 'Jennifer') + .forUpdate() + .skipLocked() + + testSql(query, dialect, { + postgres: { + sql: 'select "last_name" from "person" where "first_name" = $1 for update skip locked', + parameters: ['Jennifer'], + }, + mysql: { + sql: 'select `last_name` from `person` where `first_name` = ? for update skip locked', + parameters: ['Jennifer'], + }, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + const persons = await query.execute() + + expect(persons).to.have.length(1) + expect(persons).to.eql([{ last_name: 'Aniston' }]) + }) + + it('should select a row for update of with skip locked', async () => { + const query = ctx.db + .selectFrom('person') + .select('last_name') + .where('first_name', '=', 'Jennifer') + .forUpdate(['person']) + .skipLocked() + + testSql(query, dialect, { + postgres: { + sql: 'select "last_name" from "person" where "first_name" = $1 for update of "person" skip locked', + parameters: ['Jennifer'], + }, + mysql: { + sql: 'select `last_name` from `person` where `first_name` = ? for update of `person` skip locked', + parameters: ['Jennifer'], + }, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + const persons = await query.execute() + + expect(persons).to.have.length(1) + expect(persons).to.eql([{ last_name: 'Aniston' }]) + }) + + it('should select a row for update with skipLocked called before forUpdate', async () => { + const query = ctx.db + .selectFrom('person') + .select('last_name') + .where('first_name', '=', 'Jennifer') + .skipLocked() + .forUpdate() + + testSql(query, dialect, { + postgres: { + sql: 'select "last_name" from "person" where "first_name" = $1 for update skip locked', + parameters: ['Jennifer'], + }, + mysql: { + sql: 'select `last_name` from `person` where `first_name` = ? for update skip locked', + parameters: ['Jennifer'], + }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -589,6 +768,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -601,7 +781,7 @@ for (const dialect of DIALECTS) { ]) }) - it('should select with distict on that uses a RawBuilder expression', async () => { + it('should select with distinct on that uses a RawBuilder expression', async () => { const query = ctx.db .selectFrom('person') .select(['first_name', 'last_name']) @@ -613,6 +793,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -646,6 +827,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -673,6 +855,10 @@ for (const dialect of DIALECTS) { sql: 'select max(`person`.`first_name`) as `max_first_name`, min(`person`.`first_name`) as `min_first_name` from `person`', parameters: [], }, + mssql: { + sql: 'select max("person"."first_name") as "max_first_name", min("person"."first_name") as "min_first_name" from "person"', + parameters: [], + }, sqlite: { sql: 'select max("person"."first_name") as "max_first_name", min("person"."first_name") as "min_first_name" from "person"', parameters: [], @@ -686,6 +872,36 @@ for (const dialect of DIALECTS) { expect(max_first_name).to.equal('Sylvester') }) + it('should use a cast in a select call', async () => { + const query = ctx.db + .selectFrom('toy') + .select((eb) => [ + eb.cast('price', 'double precision').as('price'), + ]) + + testSql(query, dialect, { + postgres: { + sql: 'select cast("price" as double precision) as "price" from "toy"', + parameters: [], + }, + mysql: { + sql: 'select cast(`price` as double precision) as `price` from `toy`', + parameters: [], + }, + mssql: { + sql: 'select cast("price" as double precision) as "price" from "toy"', + parameters: [], + }, + sqlite: { + sql: 'select cast("price" as double precision) as "price" from "toy"', + parameters: [], + }, + }) + + const { price } = await query.executeTakeFirstOrThrow() + expect(price).to.equal(10) + }) + it('modifyFront should add arbitrary SQL to the front of the query', async () => { const query = ctx.db .selectFrom('person') @@ -702,6 +918,10 @@ for (const dialect of DIALECTS) { sql: 'select distinct `gender` from `person` order by `gender`', parameters: [], }, + mssql: { + sql: 'select distinct "gender" from "person" order by "gender"', + parameters: [], + }, sqlite: { sql: 'select distinct "gender" from "person" order by "gender"', parameters: [], @@ -714,7 +934,7 @@ for (const dialect of DIALECTS) { expect(persons).to.eql([{ gender: 'female' }, { gender: 'male' }]) }) - if (dialect !== 'sqlite') { + if (dialect === 'postgres' || dialect === 'mysql') { it('modifyEnd should add arbitrary SQL to the end of the query', async () => { const query = ctx.db .selectFrom('person') @@ -731,6 +951,7 @@ for (const dialect of DIALECTS) { sql: 'select `last_name` from `person` where `first_name` = ? for update', parameters: ['Jennifer'], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -741,8 +962,37 @@ for (const dialect of DIALECTS) { }) } - if (dialect === 'mysql' || dialect === 'postgres') { - it('should stream results', async () => { + it('should stream results', async () => { + const males: unknown[] = [] + + const stream = ctx.db + .selectFrom('person') + .select(['first_name', 'last_name', 'gender']) + .where('gender', '=', 'male') + .orderBy('first_name') + .stream() + + for await (const male of stream) { + males.push(male) + } + + expect(males).to.have.length(2) + expect(males).to.eql([ + { + first_name: 'Arnold', + last_name: 'Schwarzenegger', + gender: 'male', + }, + { + first_name: 'Sylvester', + last_name: 'Stallone', + gender: 'male', + }, + ]) + }) + + if (dialect === 'postgres' || dialect === 'mssql') { + it('should stream results with a specific chunk size', async () => { const males: unknown[] = [] const stream = ctx.db @@ -750,7 +1000,7 @@ for (const dialect of DIALECTS) { .select(['first_name', 'last_name', 'gender']) .where('gender', '=', 'male') .orderBy('first_name') - .stream() + .stream(1) for await (const male of stream) { males.push(male) @@ -770,116 +1020,319 @@ for (const dialect of DIALECTS) { }, ]) }) + } - if (dialect === 'postgres') { - it('should stream results with a specific chunk size', async () => { - const males: unknown[] = [] + it('should release connection on premature async iterator stop', async () => { + for (let i = 0; i <= POOL_SIZE + 1; i++) { + const stream = ctx.db.selectFrom('person').selectAll().stream() - const stream = ctx.db - .selectFrom('person') - .select(['first_name', 'last_name', 'gender']) - .where('gender', '=', 'male') - .orderBy('first_name') - .stream(1) + for await (const _ of stream) { + break + } + } + }) - for await (const male of stream) { - males.push(male) - } + it('should release connection on premature async iterator stop when using a specific chunk size', async () => { + for (let i = 0; i <= POOL_SIZE + 1; i++) { + const stream = ctx.db.selectFrom('person').selectAll().stream(1) - expect(males).to.have.length(2) - expect(males).to.eql([ - { - first_name: 'Arnold', - last_name: 'Schwarzenegger', - gender: 'male', - }, - { - first_name: 'Sylvester', - last_name: 'Stallone', - gender: 'male', - }, - ]) - }) + for await (const _ of stream) { + break + } } + }) + + if (dialect === 'postgres') { + it('should throw an error if the cursor implementation is not provided for the postgres dialect', async () => { + const db = new Kysely({ + dialect: new PostgresDialect({ + pool: async () => new Pool(DIALECT_CONFIGS.postgres), + }), + plugins: PLUGINS, + }) - it('should release connection on premature async iterator stop', async () => { - for (let i = 0; i <= POOL_SIZE + 1; i++) { - const stream = ctx.db.selectFrom('person').selectAll().stream() + await expect( + (async () => { + for await (const _ of db + .selectFrom('person') + .selectAll() + .stream()) { + } + })(), + ).to.be.rejectedWith( + "'cursor' is not present in your postgres dialect config. It's required to make streaming work in postgres.", + ) - for await (const _ of stream) { - break - } - } + await db.destroy() }) + } - it('should release connection on premature async iterator stop when using a specific chunk size', async () => { - for (let i = 0; i <= POOL_SIZE + 1; i++) { - const stream = ctx.db.selectFrom('person').selectAll().stream(1) + if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'sqlite') { + it('should create a select query with limit and offset', async () => { + const query = ctx.db + .selectFrom('person') + .select('first_name') + .limit(2) + .offset(1) - for await (const _ of stream) { - break - } - } - }) + testSql(query, dialect, { + postgres: { + sql: `select "first_name" from "person" limit $1 offset $2`, + parameters: [2, 1], + }, + mysql: { + sql: 'select `first_name` from `person` limit ? offset ?', + parameters: [2, 1], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'select "first_name" from "person" limit ? offset ?', + parameters: [2, 1], + }, + }) - if (dialect === 'postgres') { - it('should throw an error if the cursor implementation is not provided for the postgres dialect', async () => { - const db = new Kysely({ - dialect: new PostgresDialect({ - pool: async () => new Pool(DIALECT_CONFIGS.postgres), - }), - plugins: PLUGINS, - }) + const result = await query.execute() + expect(result).to.have.length(2) + }) - await expect( - (async () => { - for await (const _ of db - .selectFrom('person') - .selectAll() - .stream()) { - } - })() - ).to.be.rejectedWith( - "'cursor' is not present in your postgres dialect config. It's required to make streaming work in postgres." - ) + it('should create a select query with limit and offset expressions', async () => { + const query = ctx.db + .selectFrom('person') + .select('first_name') + .limit((eb) => eb.lit(2)) + .offset((eb) => eb.lit(1)) - await db.destroy() + testSql(query, dialect, { + postgres: { + sql: `select "first_name" from "person" limit 2 offset 1`, + parameters: [], + }, + mysql: { + sql: 'select `first_name` from `person` limit 2 offset 1', + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'select "first_name" from "person" limit 2 offset 1', + parameters: [], + }, }) - } + + const result = await query.execute() + expect(result).to.have.length(2) + }) } - it.skip('perf', async () => { - const ids = Array.from({ length: 100 }).map(() => - Math.round(Math.random() * 1000) - ) - - function test() { - return ctx.db - .updateTable('person') - .set({ - first_name: 'foo', - last_name: 'bar', - id: 100, - gender: 'other', - }) - .where('id', 'in', ids) - .compile() - } + it('should create a select statement without a `from` clause', async () => { + const query = ctx.db.selectNoFrom((eb) => [ + eb + .selectFrom('person') + .select('first_name') + .orderBy('first_name') + .$call(limit(1, dialect)) + .as('person_first_name'), + ]) - // Warmup - for (let i = 0; i < 1000; ++i) { - test() - } + testSql(query, dialect, { + postgres: { + sql: `select (select "first_name" from "person" order by "first_name" limit $1) as "person_first_name"`, + parameters: [1], + }, + mysql: { + sql: 'select (select `first_name` from `person` order by `first_name` limit ?) as `person_first_name`', + parameters: [1], + }, + mssql: { + sql: `select (select top(1) "first_name" from "person" order by "first_name") as "person_first_name"`, + parameters: [], + }, + sqlite: { + sql: 'select (select "first_name" from "person" order by "first_name" limit ?) as "person_first_name"', + parameters: [1], + }, + }) - const time = Date.now() - const N = 100000 + const result = await query.execute() + expect(result).to.have.length(1) - for (let i = 0; i < N; ++i) { - test() + if (dialect === 'mysql') { + // For some weird reason, MySQL returns `one` as a string. + expect(result[0]).to.eql({ person_first_name: 'Arnold' }) + } else { + expect(result[0]).to.eql({ person_first_name: 'Arnold' }) } - - const endTime = Date.now() - console.log((endTime - time) / N) }) + + if (dialect === 'postgres' || dialect === 'mssql') { + it('should create a select query with order by, offset and fetch', async () => { + const query = ctx.db + .selectFrom('person') + .select('first_name') + .orderBy('first_name') + .offset(1) + .fetch(2) + + testSql(query, dialect, { + postgres: { + sql: 'select "first_name" from "person" order by "first_name" offset $1 fetch next $2 rows only', + parameters: [1, 2], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'select "first_name" from "person" order by "first_name" offset @1 rows fetch next @2 rows only', + parameters: [1, 2], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.execute() + expect(result).to.have.length(2) + }) + + it('should create a select query with order by, offset and fetch only', async () => { + const query = ctx.db + .selectFrom('person') + .select('first_name') + .orderBy('first_name') + .offset(1) + .fetch(2, 'only') + + testSql(query, dialect, { + postgres: { + sql: 'select "first_name" from "person" order by "first_name" offset $1 fetch next $2 rows only', + parameters: [1, 2], + }, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'select "first_name" from "person" order by "first_name" offset @1 rows fetch next @2 rows only', + parameters: [1, 2], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.execute() + expect(result).to.have.length(2) + }) + } + + if (dialect === 'postgres') { + it('should create a select query with order by, offset and fetch with ties', async () => { + const query = ctx.db + .selectFrom('person') + .select('first_name') + .orderBy('first_name') + .offset(1) + .fetch(2, 'with ties') + + testSql(query, dialect, { + postgres: { + sql: 'select "first_name" from "person" order by "first_name" offset $1 fetch next $2 rows with ties', + parameters: [1, 2], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + } + + if (dialect === 'mssql') { + it('should create a select query with top', async () => { + const query = ctx.db.selectFrom('person').select('first_name').top(2) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'select top(2) "first_name" from "person"', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + + it('should create a select query with top and order by', async () => { + const query = ctx.db + .selectFrom('person') + .select('first_name') + .top(2) + .orderBy('first_name') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'select top(2) "first_name" from "person" order by "first_name"', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + + it('should create a select query with top percent', async () => { + const query = ctx.db + .selectFrom('person') + .select('first_name') + .top(50, 'percent') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'select top(50) percent "first_name" from "person"', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + + it('should create a select query with top with ties', async () => { + const query = ctx.db + .selectFrom('person') + .select('first_name') + .top(2, 'with ties') + .orderBy('first_name') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'select top(2) with ties "first_name" from "person" order by "first_name"', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + + it('should create a select query with top percent with ties', async () => { + const query = ctx.db + .selectFrom('person') + .select('first_name') + .top(50, 'percent with ties') + .orderBy('first_name') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'select top(50) percent with ties "first_name" from "person" order by "first_name"', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + } }) } diff --git a/test/node/src/set-operation.test.ts b/test/node/src/set-operation.test.ts index a3ebf5408..3c7f7abec 100644 --- a/test/node/src/set-operation.test.ts +++ b/test/node/src/set-operation.test.ts @@ -1,5 +1,4 @@ import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -8,6 +7,7 @@ import { expect, insertDefaultDataSet, NOT_SUPPORTED, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -46,6 +46,10 @@ for (const dialect of DIALECTS) { sql: 'select `id`, `first_name` as `name` from `person` union select `id`, `name` from `pet` order by `name`', parameters: [], }, + mssql: { + sql: 'select "id", "first_name" as "name" from "person" union select "id", "name" from "pet" order by "name"', + parameters: [], + }, sqlite: { sql: 'select "id", "first_name" as "name" from "person" union select "id", "name" from "pet" order by "name"', parameters: [], @@ -63,6 +67,135 @@ for (const dialect of DIALECTS) { ]) }) + it('should combine multiple select queries using union with an array', async () => { + const query = ctx.db + .selectFrom('person') + .select(['id', 'first_name as name']) + .union([ + ctx.db.selectFrom('pet').select(['id', 'name']), + ctx.db.selectFrom('pet').select(['id', 'species as name']), + ]) + .orderBy('name') + + testSql(query, dialect, { + postgres: { + sql: 'select "id", "first_name" as "name" from "person" union select "id", "name" from "pet" union select "id", "species" as "name" from "pet" order by "name"', + parameters: [], + }, + mysql: { + sql: 'select `id`, `first_name` as `name` from `person` union select `id`, `name` from `pet` union select `id`, `species` as `name` from `pet` order by `name`', + parameters: [], + }, + mssql: { + sql: 'select "id", "first_name" as "name" from "person" union select "id", "name" from "pet" union select "id", "species" as "name" from "pet" order by "name"', + parameters: [], + }, + sqlite: { + sql: 'select "id", "first_name" as "name" from "person" union select "id", "name" from "pet" union select "id", "species" as "name" from "pet" order by "name"', + parameters: [], + }, + }) + + const result = await query.execute() + expect(result).to.containSubset([ + { name: 'Arnold' }, + { name: 'Catto' }, + { name: 'Doggo' }, + { name: 'Hammo' }, + { name: 'Jennifer' }, + { name: 'Sylvester' }, + { name: 'cat' }, + { name: 'dog' }, + { name: 'hamster' }, + ]) + }) + + it('should combine multiple select queries using union with a callback returning an array', async () => { + const query = ctx.db + .selectFrom('person') + .select(['id', 'first_name as name']) + .union((eb) => [ + eb.selectFrom('pet').select(['id', 'name']), + eb.selectFrom('pet').select(['id', 'species as name']), + ]) + .orderBy('name') + + testSql(query, dialect, { + postgres: { + sql: 'select "id", "first_name" as "name" from "person" union select "id", "name" from "pet" union select "id", "species" as "name" from "pet" order by "name"', + parameters: [], + }, + mysql: { + sql: 'select `id`, `first_name` as `name` from `person` union select `id`, `name` from `pet` union select `id`, `species` as `name` from `pet` order by `name`', + parameters: [], + }, + mssql: { + sql: 'select "id", "first_name" as "name" from "person" union select "id", "name" from "pet" union select "id", "species" as "name" from "pet" order by "name"', + parameters: [], + }, + sqlite: { + sql: 'select "id", "first_name" as "name" from "person" union select "id", "name" from "pet" union select "id", "species" as "name" from "pet" order by "name"', + parameters: [], + }, + }) + + const result = await query.execute() + expect(result).to.containSubset([ + { name: 'Arnold' }, + { name: 'Catto' }, + { name: 'Doggo' }, + { name: 'Hammo' }, + { name: 'Jennifer' }, + { name: 'Sylvester' }, + { name: 'cat' }, + { name: 'dog' }, + { name: 'hamster' }, + ]) + }) + + if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'mssql') { + it('should combine three select queries using union and an expression builder', async () => { + const query = ctx.db + .selectFrom('person') + .select(['id', 'first_name as name']) + .union((eb) => + eb.parens( + eb + .selectFrom('pet') + .select(['id', 'name']) + .union(eb.selectFrom('toy').select(['id', 'name'])), + ), + ) + .orderBy('name') + + testSql(query, dialect, { + postgres: { + sql: 'select "id", "first_name" as "name" from "person" union (select "id", "name" from "pet" union select "id", "name" from "toy") order by "name"', + parameters: [], + }, + mysql: { + sql: 'select `id`, `first_name` as `name` from `person` union (select `id`, `name` from `pet` union select `id`, `name` from `toy`) order by `name`', + parameters: [], + }, + mssql: { + sql: 'select "id", "first_name" as "name" from "person" union (select "id", "name" from "pet" union select "id", "name" from "toy") order by "name"', + parameters: [], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.execute() + expect(result).to.containSubset([ + { name: 'Arnold' }, + { name: 'Catto' }, + { name: 'Doggo' }, + { name: 'Hammo' }, + { name: 'Jennifer' }, + { name: 'Sylvester' }, + ]) + }) + } + it('should combine two select queries using union all', async () => { const query = ctx.db .selectFrom('person') @@ -79,6 +212,10 @@ for (const dialect of DIALECTS) { sql: 'select `id`, `first_name` as `name` from `person` union all select `id`, `name` from `pet` order by `name`', parameters: [], }, + mssql: { + sql: 'select "id", "first_name" as "name" from "person" union all select "id", "name" from "pet" order by "name"', + parameters: [], + }, sqlite: { sql: 'select "id", "first_name" as "name" from "person" union all select "id", "name" from "pet" order by "name"', parameters: [], @@ -113,6 +250,10 @@ for (const dialect of DIALECTS) { sql: 'select `id`, `first_name` as `name` from `person` union all select `id`, `name` from `pet` union select `id`, `name` from `toy` order by `name`', parameters: [], }, + mssql: { + sql: 'select "id", "first_name" as "name" from "person" union all select "id", "name" from "pet" union select "id", "name" from "toy" order by "name"', + parameters: [], + }, sqlite: { sql: 'select "id", "first_name" as "name" from "person" union all select "id", "name" from "pet" union select "id", "name" from "toy" order by "name"', parameters: [], @@ -122,7 +263,7 @@ for (const dialect of DIALECTS) { await query.execute() }) - if (dialect === 'postgres' || dialect === 'sqlite') { + if (dialect === 'postgres' || dialect === 'mssql' || dialect === 'sqlite') { it('should combine two select queries using intersect', async () => { const query = ctx.db .selectFrom('person') @@ -136,6 +277,10 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'select "id", "first_name" as "name" from "person" intersect select "id", "name" from "pet" order by "name"', + parameters: [], + }, sqlite: { sql: 'select "id", "first_name" as "name" from "person" intersect select "id", "name" from "pet" order by "name"', parameters: [], @@ -158,6 +303,10 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'select "id", "first_name" as "name" from "person" except select "id", "name" from "pet" order by "name"', + parameters: [], + }, sqlite: { sql: 'select "id", "first_name" as "name" from "person" except select "id", "name" from "pet" order by "name"', parameters: [], @@ -183,6 +332,10 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'select "id", "first_name" as "name" from "person" union select "id", "name" from "pet" union all select "id", "name" from "toy" intersect select "id", "name" from "pet" except select "id", "name" from "toy" order by "name"', + parameters: [], + }, sqlite: { sql: 'select "id", "first_name" as "name" from "person" union select "id", "name" from "pet" union all select "id", "name" from "toy" intersect select "id", "name" from "pet" except select "id", "name" from "toy" order by "name"', parameters: [], @@ -207,6 +360,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -226,6 +380,7 @@ for (const dialect of DIALECTS) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) diff --git a/test/node/src/test-setup.ts b/test/node/src/test-setup.ts index 6dee0c6c0..a85d6e273 100644 --- a/test/node/src/test-setup.ts +++ b/test/node/src/test-setup.ts @@ -2,9 +2,12 @@ import * as chai from 'chai' import * as chaiAsPromised from 'chai-as-promised' import * as chaiSubset from 'chai-subset' import * as Cursor from 'pg-cursor' -import { Pool } from 'pg' +import { Pool, PoolConfig } from 'pg' import { createPool } from 'mysql2' import * as Database from 'better-sqlite3' +import * as Tarn from 'tarn' +import * as Tedious from 'tedious' +import { PoolOptions } from 'mysql2' chai.use(chaiSubset) chai.use(chaiAsPromised) @@ -31,22 +34,33 @@ import { sql, ColumnType, InsertObject, + MssqlDialect, + SelectQueryBuilder, } from '../../../' +import { + OrderByDirection, + UndirectedOrderByExpression, +} from '../../../dist/cjs/parser/order-by-parser' + +export type Gender = 'male' | 'female' | 'other' +export type MaritalStatus = 'single' | 'married' | 'divorced' | 'widowed' +export type Species = 'dog' | 'cat' | 'hamster' export interface Person { id: Generated first_name: string | null middle_name: ColumnType last_name: string | null - gender: 'male' | 'female' | 'other' - marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null + gender: Gender + marital_status: MaritalStatus | null + children: Generated } export interface Pet { id: Generated name: string owner_id: number - species: 'dog' | 'cat' | 'hamster' + species: Species } export interface Toy { @@ -77,12 +91,18 @@ export interface TestContext { db: Kysely } -export type BuiltInDialect = 'postgres' | 'mysql' | 'sqlite' +export type BuiltInDialect = 'postgres' | 'mysql' | 'mssql' | 'sqlite' export type PerDialect = Record export const DIALECTS: BuiltInDialect[] = ( - ['postgres', 'mysql', 'sqlite'] as const -).filter((d) => !process.env.DIALECT || d === process.env.DIALECT) + ['postgres', 'mysql', 'mssql', 'sqlite'] as const +).filter( + (d) => + !process.env.DIALECTS || + process.env.DIALECTS.split(',') + .map((it) => it.trim()) + .includes(d), +) const TEST_INIT_TIMEOUT = 5 * 60 * 1000 // This can be used as a placeholder for testSql when a query is not @@ -108,7 +128,7 @@ export const DIALECT_CONFIGS = { user: 'kysely', port: 5434, max: POOL_SIZE, - }, + } satisfies PoolConfig, mysql: { database: 'kysely_test', @@ -121,14 +141,31 @@ export const DIALECT_CONFIGS = { bigNumberStrings: true, connectionLimit: POOL_SIZE, - }, + } satisfies PoolOptions, + + mssql: { + authentication: { + options: { + password: 'KyselyTest0', + userName: 'sa', + }, + type: 'default', + }, + options: { + connectTimeout: 3000, + database: 'kysely_test', + port: 21433, + trustServerCertificate: true, + }, + server: 'localhost', + } satisfies Tedious.ConnectionConfig, sqlite: { databasePath: ':memory:', }, } -const DB_CONFIGS: PerDialect = { +export const DB_CONFIGS: PerDialect = { postgres: { dialect: new PostgresDialect({ pool: async () => new Pool(DIALECT_CONFIGS.postgres), @@ -144,6 +181,23 @@ const DB_CONFIGS: PerDialect = { plugins: PLUGINS, }, + mssql: { + dialect: new MssqlDialect({ + tarn: { + options: { + max: POOL_SIZE, + min: 0, + }, + ...Tarn, + }, + tedious: { + ...Tedious, + connectionFactory: () => new Tedious.Connection(DIALECT_CONFIGS.mssql), + }, + }), + plugins: PLUGINS, + }, + sqlite: { dialect: new SqliteDialect({ database: async () => new Database(DIALECT_CONFIGS.sqlite.databasePath), @@ -155,7 +209,7 @@ const DB_CONFIGS: PerDialect = { export async function initTest( ctx: Mocha.Context, dialect: BuiltInDialect, - log?: Logger + log?: Logger, ): Promise { const config = DB_CONFIGS[dialect] @@ -176,14 +230,14 @@ export async function destroyTest(ctx: TestContext): Promise { export async function insertPersons( ctx: TestContext, - insertPersons: PersonInsertParams[] + insertPersons: PersonInsertParams[], ): Promise { for (const insertPerson of insertPersons) { const { pets, ...person } = insertPerson const personId = await insert( - ctx.dialect, - ctx.db.insertInto('person').values({ ...person }) + ctx, + ctx.db.insertInto('person').values({ ...person }), ) for (const insertPet of pets ?? []) { @@ -229,7 +283,7 @@ export async function clearDatabase(ctx: TestContext): Promise { export function testSql( query: Compilable, dialect: BuiltInDialect, - expectedPerDialect: PerDialect<{ sql: string | string[]; parameters: any[] }> + expectedPerDialect: PerDialect<{ sql: string | string[]; parameters: any[] }>, ): void { const expected = expectedPerDialect[dialect] const expectedSql = Array.isArray(expected.sql) @@ -243,7 +297,7 @@ export function testSql( async function createDatabase( db: Kysely, - dialect: BuiltInDialect + dialect: BuiltInDialect, ): Promise { await dropDatabase(db) @@ -253,21 +307,51 @@ async function createDatabase( .addColumn('last_name', 'varchar(255)') .addColumn('gender', 'varchar(50)', (col) => col.notNull()) .addColumn('marital_status', 'varchar(50)') + .addColumn('children', 'integer', (col) => col.notNull().defaultTo(0)) .execute() await createTableWithId(db.schema, dialect, 'pet') .addColumn('name', 'varchar(255)', (col) => col.unique().notNull()) .addColumn('owner_id', 'integer', (col) => - col.references('person.id').onDelete('cascade').notNull() + col.references('person.id').onDelete('cascade').notNull(), ) .addColumn('species', 'varchar(50)', (col) => col.notNull()) .execute() - await createTableWithId(db.schema, dialect, 'toy') + const createToyTableBase = createTableWithId(db.schema, dialect, 'toy') .addColumn('name', 'varchar(255)', (col) => col.notNull()) .addColumn('pet_id', 'integer', (col) => col.references('pet.id').notNull()) - .addColumn('price', 'double precision', (col) => col.notNull()) - .execute() + + if (dialect === 'postgres') { + await createToyTableBase + .addColumn('price', 'double precision', (col) => col.notNull()) + .execute() + await sql`COMMENT ON COLUMN toy.price IS 'Price in USD';`.execute(db) + } + + if (dialect === 'mssql') { + await createToyTableBase + .addColumn('price', 'double precision', (col) => col.notNull()) + .execute() + await sql`EXECUTE sp_addextendedproperty N'MS_Description', N'Price in USD', N'SCHEMA', N'dbo', N'TABLE', 'toy', N'COLUMN', N'price'`.execute( + db, + ) + } + + if (dialect === 'mysql') { + await createToyTableBase + .addColumn('price', 'double precision', (col) => + col.notNull().modifyEnd(sql`comment ${sql.lit('Price in USD')}`), + ) + .execute() + } + + if (dialect === 'sqlite') { + // there is no way to add a comment + await createToyTableBase + .addColumn('price', 'double precision', (col) => col.notNull()) + .execute() + } await db.schema .createIndex('pet_owner_id_index') @@ -279,17 +363,23 @@ async function createDatabase( export function createTableWithId( schema: SchemaModule, dialect: BuiltInDialect, - tableName: string + tableName: string, ) { const builder = schema.createTable(tableName) if (dialect === 'postgres') { return builder.addColumn('id', 'serial', (col) => col.primaryKey()) - } else { + } + + if (dialect === 'mssql') { return builder.addColumn('id', 'integer', (col) => - col.autoIncrement().primaryKey() + col.identity().notNull().primaryKey() ) } + + return builder.addColumn('id', 'integer', (col) => + col.autoIncrement().primaryKey(), + ) } async function connect(config: KyselyConfig): Promise> { @@ -308,7 +398,7 @@ async function connect(config: KyselyConfig): Promise> { } console.log( - 'Waiting for the database to become available. Did you remember to run `docker-compose up`?' + 'Waiting for the database to become available. Did you remember to run `docker-compose up`?', ) await sleep(1000) @@ -329,13 +419,13 @@ export const expect = chai.expect async function insertPetForPerson( ctx: TestContext, personId: number, - insertPet: PetInsertParams + insertPet: PetInsertParams, ): Promise { const { toys, ...pet } = insertPet const petId = await insert( - ctx.dialect, - ctx.db.insertInto('pet').values({ ...pet, owner_id: personId }) + ctx, + ctx.db.insertInto('pet').values({ ...pet, owner_id: personId }), ) for (const toy of toys ?? []) { @@ -346,7 +436,7 @@ async function insertPetForPerson( async function insertToysForPet( ctx: TestContext, petId: number, - toy: Omit + toy: Omit, ): Promise { await ctx.db .insertInto('toy') @@ -354,17 +444,30 @@ async function insertToysForPet( .executeTakeFirst() } -async function insert( - dialect: BuiltInDialect, - qb: InsertQueryBuilder +export async function insert( + ctx: TestContext, + qb: InsertQueryBuilder, ): Promise { + const { dialect } = ctx + if (dialect === 'postgres' || dialect === 'sqlite') { const { id } = await qb.returning('id').executeTakeFirstOrThrow() + return id - } else { - const { insertId } = await qb.executeTakeFirst() - return Number(insertId) } + + if (dialect === 'mssql') { + const { id } = await qb + .output('inserted.id' as any) + .$castTo<{ id: number }>() + .executeTakeFirstOrThrow() + + return id + } + + const { insertId } = await qb.executeTakeFirstOrThrow() + + return Number(insertId) } function createNoopTransformerPlugin(): KyselyPlugin { @@ -376,7 +479,7 @@ function createNoopTransformerPlugin(): KyselyPlugin { }, async transformResult( - args: PluginTransformResultArgs + args: PluginTransformResultArgs, ): Promise> { return args.result }, @@ -386,3 +489,37 @@ function createNoopTransformerPlugin(): KyselyPlugin { function sleep(millis: number): Promise { return new Promise((resolve) => setTimeout(resolve, millis)) } + +export function limit>( + limit: number, + dialect: BuiltInDialect, +): (qb: QB) => QB { + return (qb) => { + if (dialect === 'mssql') { + return qb.top(limit) as QB + } + + return qb.limit(limit) as QB + } +} + +export function orderBy>( + orderBy: QB extends SelectQueryBuilder + ? UndirectedOrderByExpression + : never, + direction: OrderByDirection | undefined, + dialect: BuiltInDialect, +): (qb: QB) => QB { + return (qb) => { + if (dialect === 'mssql') { + return qb.orderBy( + orderBy, + sql`${sql.raw(direction ? `${direction} ` : '')}${sql.raw( + 'offset 0 rows', + )}`, + ) as QB + } + + return qb.orderBy(orderBy, direction) as QB + } +} diff --git a/test/node/src/transaction.test.ts b/test/node/src/transaction.test.ts index 15b3c33a8..2c7ec2afa 100644 --- a/test/node/src/transaction.test.ts +++ b/test/node/src/transaction.test.ts @@ -1,7 +1,8 @@ -import { CompiledQuery, Transaction } from '../../../' +import * as sinon from 'sinon' +import { Connection, ISOLATION_LEVEL } from 'tedious' +import { CompiledQuery, IsolationLevel, Transaction } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -9,12 +10,24 @@ import { expect, Database, insertDefaultDataSet, + DIALECTS, } from './test-setup.js' +import { DatabaseError as PostgresError } from 'pg' +import { SqliteError } from 'better-sqlite3' for (const dialect of DIALECTS) { describe(`${dialect}: transaction`, () => { let ctx: TestContext - let executedQueries: CompiledQuery[] = [] + const executedQueries: CompiledQuery[] = [] + const sandbox = sinon.createSandbox() + let tediousBeginTransactionSpy: sinon.SinonSpy< + Parameters, + ReturnType + > + let tediousCommitTransactionSpy: sinon.SinonSpy< + Parameters, + ReturnType + > before(async function () { ctx = await initTest(this, dialect, (event) => { @@ -26,73 +39,113 @@ for (const dialect of DIALECTS) { beforeEach(async () => { await insertDefaultDataSet(ctx) - executedQueries = [] + executedQueries.length = 0 + tediousBeginTransactionSpy = sandbox.spy( + Connection.prototype, + 'beginTransaction', + ) + tediousCommitTransactionSpy = sandbox.spy( + Connection.prototype, + 'commitTransaction', + ) }) afterEach(async () => { await clearDatabase(ctx) + sandbox.restore() }) after(async () => { await destroyTest(ctx) }) - if (dialect !== 'sqlite') { - it('should set the transaction isolation level', async () => { - await ctx.db - .transaction() - .setIsolationLevel('serializable') - .execute(async (trx) => { - await trx - .insertInto('person') - .values({ - first_name: 'Foo', - last_name: 'Barson', - gender: 'male', - }) - .execute() - }) + if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'mssql') { + for (const isolationLevel of [ + 'read uncommitted', + 'read committed', + 'repeatable read', + 'serializable', + ...(dialect === 'mssql' ? (['snapshot'] as const) : []), + ] satisfies IsolationLevel[]) { + it(`should set the transaction isolation level as "${isolationLevel}"`, async () => { + await ctx.db + .transaction() + .setIsolationLevel(isolationLevel) + .execute(async (trx) => { + await trx + .insertInto('person') + .values({ + first_name: 'Foo', + last_name: 'Barson', + gender: 'male', + }) + .execute() + }) - if (dialect == 'postgres') { - expect( - executedQueries.map((it) => ({ - sql: it.sql, - parameters: it.parameters, - })) - ).to.eql([ - { - sql: 'start transaction isolation level serializable', - parameters: [], - }, - { - sql: 'insert into "person" ("first_name", "last_name", "gender") values ($1, $2, $3)', - parameters: ['Foo', 'Barson', 'male'], - }, - { sql: 'commit', parameters: [] }, - ]) - } else if (dialect === 'mysql') { - expect( - executedQueries.map((it) => ({ - sql: it.sql, - parameters: it.parameters, - })) - ).to.eql([ - { - sql: 'set transaction isolation level serializable', - parameters: [], - }, - { - sql: 'begin', - parameters: [], - }, - { - sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)', - parameters: ['Foo', 'Barson', 'male'], - }, - { sql: 'commit', parameters: [] }, - ]) - } - }) + if (dialect == 'postgres') { + expect( + executedQueries.map((it) => ({ + sql: it.sql, + parameters: it.parameters, + })), + ).to.eql([ + { + sql: `start transaction isolation level ${isolationLevel}`, + parameters: [], + }, + { + sql: 'insert into "person" ("first_name", "last_name", "gender") values ($1, $2, $3)', + parameters: ['Foo', 'Barson', 'male'], + }, + { sql: 'commit', parameters: [] }, + ]) + } else if (dialect === 'mysql') { + expect( + executedQueries.map((it) => ({ + sql: it.sql, + parameters: it.parameters, + })), + ).to.eql([ + { + sql: `set transaction isolation level ${isolationLevel}`, + parameters: [], + }, + { + sql: 'begin', + parameters: [], + }, + { + sql: 'insert into `person` (`first_name`, `last_name`, `gender`) values (?, ?, ?)', + parameters: ['Foo', 'Barson', 'male'], + }, + { sql: 'commit', parameters: [] }, + ]) + } else if (dialect === 'mssql') { + expect(tediousBeginTransactionSpy.calledOnce).to.be.true + expect(tediousBeginTransactionSpy.getCall(0).args[1]).to.not.be + .undefined + expect(tediousBeginTransactionSpy.getCall(0).args[2]).to.equal( + ISOLATION_LEVEL[ + isolationLevel.replace(' ', '_').toUpperCase() as any + ], + ) + + expect( + executedQueries.map((it) => ({ + sql: it.sql, + parameters: it.parameters, + })), + ).to.eql([ + { + sql: 'insert into "person" ("first_name", "last_name", "gender") values (@1, @2, @3)', + parameters: ['Foo', 'Barson', 'male'], + }, + ]) + + expect(tediousCommitTransactionSpy.calledOnce).to.be.true + } + }) + } } if (dialect === 'postgres') { @@ -122,7 +175,7 @@ for (const dialect of DIALECTS) { })) const results = await Promise.allSettled( - threads.map((thread) => executeThread(thread.id, thread.fails)) + threads.map((thread) => executeThread(thread.id, thread.fails)), ) for (let i = 0; i < threads.length; ++i) { @@ -154,9 +207,27 @@ for (const dialect of DIALECTS) { } }) + it('should retain the full stack trace', async () => { + try { + await ctx.db.transaction().execute(async (trx) => { + await trx.selectFrom('person').where('id', 'in', -1).execute() + }) + + expect.fail('Expected transaction to fail') + } catch (error) { + if (dialect === 'sqlite') { + expect(error).to.be.instanceOf(SqliteError) + } else if (dialect === 'postgres') { + expect(error).to.be.instanceOf(PostgresError) + } + + expect((error as Error).stack).to.include('transaction.test.js') + } + }) + async function insertPet( trx: Transaction, - ownerId: number + ownerId: number, ): Promise { await trx .insertInto('pet') @@ -170,17 +241,27 @@ for (const dialect of DIALECTS) { async function insertPerson( trx: Transaction, - id: number + id: number, ): Promise { - await trx - .insertInto('person') - .values({ - id: id, - first_name: `Person ${id}`, - last_name: null, - gender: 'other', - }) - .execute() + const query = trx.insertInto('person').values({ + id: id, + first_name: `Person ${id}`, + last_name: null, + gender: 'other', + }) + + if (dialect === 'mssql') { + const compiledQuery = query.compile() + + await trx.executeQuery( + CompiledQuery.raw( + `set identity_insert "person" on; ${compiledQuery.sql}; set identity_insert "person" off;`, + [...compiledQuery.parameters], + ), + ) + } else { + await query.execute() + } } async function doesPersonExists(id: number): Promise { diff --git a/test/node/src/update.test.ts b/test/node/src/update.test.ts index 0ef842f4b..7a5b69c18 100644 --- a/test/node/src/update.test.ts +++ b/test/node/src/update.test.ts @@ -1,7 +1,6 @@ import { UpdateResult, sql } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -11,6 +10,8 @@ import { NOT_SUPPORTED, insertDefaultDataSet, DEFAULT_DATA_SET, + DIALECTS, + limit, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -48,6 +49,10 @@ for (const dialect of DIALECTS) { sql: 'update `person` set `first_name` = ?, `last_name` = ? where `gender` = ?', parameters: ['Foo', 'Barson', 'female'], }, + mssql: { + sql: 'update "person" set "first_name" = @1, "last_name" = @2 where "gender" = @3', + parameters: ['Foo', 'Barson', 'female'], + }, sqlite: { sql: 'update "person" set "first_name" = ?, "last_name" = ? where "gender" = ?', parameters: ['Foo', 'Barson', 'female'], @@ -58,6 +63,11 @@ for (const dialect of DIALECTS) { expect(result).to.be.instanceOf(UpdateResult) expect(result.numUpdatedRows).to.equal(1n) + if (dialect === 'mysql') { + expect(result.numChangedRows).to.equal(1n) + } else { + expect(result.numChangedRows).to.undefined + } expect( await ctx.db @@ -65,7 +75,7 @@ for (const dialect of DIALECTS) { .select(['first_name', 'last_name', 'gender']) .orderBy('first_name') .orderBy('last_name') - .execute() + .execute(), ).to.eql([ { first_name: 'Arnold', last_name: 'Schwarzenegger', gender: 'male' }, { first_name: 'Foo', last_name: 'Barson', gender: 'female' }, @@ -73,24 +83,30 @@ for (const dialect of DIALECTS) { ]) }) - it('should update one row with table alias', async () => { + it('should update one row using the (key, value) variant of `set` method', async () => { const query = ctx.db - .updateTable('person as p') - .set({ first_name: 'Foo', last_name: 'Barson' }) - .where('p.gender', '=', 'female') + .updateTable('person') + .set('first_name', 'Foo') + .set((eb) => eb.ref('last_name'), 'Barson') + .set('gender', (eb) => eb.val('other' as const)) + .where('gender', '=', 'female') testSql(query, dialect, { postgres: { - sql: 'update "person" as "p" set "first_name" = $1, "last_name" = $2 where "p"."gender" = $3', - parameters: ['Foo', 'Barson', 'female'], + sql: 'update "person" set "first_name" = $1, "last_name" = $2, "gender" = $3 where "gender" = $4', + parameters: ['Foo', 'Barson', 'other', 'female'], }, mysql: { - sql: 'update `person` as `p` set `first_name` = ?, `last_name` = ? where `p`.`gender` = ?', - parameters: ['Foo', 'Barson', 'female'], + sql: 'update `person` set `first_name` = ?, `last_name` = ?, `gender` = ? where `gender` = ?', + parameters: ['Foo', 'Barson', 'other', 'female'], + }, + mssql: { + sql: 'update "person" set "first_name" = @1, "last_name" = @2, "gender" = @3 where "gender" = @4', + parameters: ['Foo', 'Barson', 'other', 'female'], }, sqlite: { - sql: 'update "person" as "p" set "first_name" = ?, "last_name" = ? where "p"."gender" = ?', - parameters: ['Foo', 'Barson', 'female'], + sql: 'update "person" set "first_name" = ?, "last_name" = ?, "gender" = ? where "gender" = ?', + parameters: ['Foo', 'Barson', 'other', 'female'], }, }) @@ -98,6 +114,11 @@ for (const dialect of DIALECTS) { expect(result).to.be.instanceOf(UpdateResult) expect(result.numUpdatedRows).to.equal(1n) + if (dialect === 'mysql') { + expect(result.numChangedRows).to.equal(1n) + } else { + expect(result.numChangedRows).to.undefined + } expect( await ctx.db @@ -105,14 +126,103 @@ for (const dialect of DIALECTS) { .select(['first_name', 'last_name', 'gender']) .orderBy('first_name') .orderBy('last_name') - .execute() + .execute(), ).to.eql([ { first_name: 'Arnold', last_name: 'Schwarzenegger', gender: 'male' }, - { first_name: 'Foo', last_name: 'Barson', gender: 'female' }, + { first_name: 'Foo', last_name: 'Barson', gender: 'other' }, { first_name: 'Sylvester', last_name: 'Stallone', gender: 'male' }, ]) }) + // mssql doesn't support table aliases in update clause, but it does support this + // with update alias set ... from table_name as alias + if (dialect === 'postgres' || dialect === 'mysql' || dialect === 'sqlite') { + it('should update one row with table alias', async () => { + const query = ctx.db + .updateTable('person as p') + .set({ first_name: 'Foo', last_name: 'Barson' }) + .where('p.gender', '=', 'female') + + testSql(query, dialect, { + postgres: { + sql: 'update "person" as "p" set "first_name" = $1, "last_name" = $2 where "p"."gender" = $3', + parameters: ['Foo', 'Barson', 'female'], + }, + mysql: { + sql: 'update `person` as `p` set `first_name` = ?, `last_name` = ? where `p`.`gender` = ?', + parameters: ['Foo', 'Barson', 'female'], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'update "person" as "p" set "first_name" = ?, "last_name" = ? where "p"."gender" = ?', + parameters: ['Foo', 'Barson', 'female'], + }, + }) + + const result = await query.executeTakeFirst() + + expect(result).to.be.instanceOf(UpdateResult) + expect(result.numUpdatedRows).to.equal(1n) + if (dialect === 'mysql') { + expect(result.numChangedRows).to.equal(1n) + } else { + expect(result.numChangedRows).to.undefined + } + + expect( + await ctx.db + .selectFrom('person') + .select(['first_name', 'last_name', 'gender']) + .orderBy('first_name') + .orderBy('last_name') + .execute(), + ).to.eql([ + { first_name: 'Arnold', last_name: 'Schwarzenegger', gender: 'male' }, + { first_name: 'Foo', last_name: 'Barson', gender: 'female' }, + { first_name: 'Sylvester', last_name: 'Stallone', gender: 'male' }, + ]) + }) + } + + if (dialect === 'mssql') { + it('should update one row with table alias in from clause', async () => { + const query = ctx.db + .updateTable('p' as 'person') + .set({ first_name: 'Foo', last_name: 'Barson' }) + .from('person as p') + .where('p.gender', '=', 'female') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'update "p" set "first_name" = @1, "last_name" = @2 from "person" as "p" where "p"."gender" = @3', + parameters: ['Foo', 'Barson', 'female'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirst() + + expect(result).to.be.instanceOf(UpdateResult) + expect(result.numUpdatedRows).to.equal(1n) + expect(result.numChangedRows).to.undefined + + expect( + await ctx.db + .selectFrom('person') + .select(['first_name', 'last_name', 'gender']) + .orderBy('first_name') + .orderBy('last_name') + .execute(), + ).to.eql([ + { first_name: 'Arnold', last_name: 'Schwarzenegger', gender: 'male' }, + { first_name: 'Foo', last_name: 'Barson', gender: 'female' }, + { first_name: 'Sylvester', last_name: 'Stallone', gender: 'male' }, + ]) + }) + } + it('should update one row using a subquery', async () => { const query = ctx.db .updateTable('person') @@ -133,6 +243,10 @@ for (const dialect of DIALECTS) { sql: 'update `person` set `last_name` = (select `name` from `pet` where `person`.`id` = `owner_id`) where `first_name` = ?', parameters: ['Jennifer'], }, + mssql: { + sql: 'update "person" set "last_name" = (select "name" from "pet" where "person"."id" = "owner_id") where "first_name" = @1', + parameters: ['Jennifer'], + }, sqlite: { sql: 'update "person" set "last_name" = (select "name" from "pet" where "person"."id" = "owner_id") where "first_name" = ?', parameters: ['Jennifer'], @@ -143,6 +257,11 @@ for (const dialect of DIALECTS) { expect(result).to.be.instanceOf(UpdateResult) expect(result.numUpdatedRows).to.equal(1n) + if (dialect === 'mysql') { + expect(result.numChangedRows).to.equal(1n) + } else { + expect(result.numChangedRows).to.undefined + } const person = await ctx.db .selectFrom('person') @@ -158,7 +277,7 @@ for (const dialect of DIALECTS) { const query = ctx.db .updateTable('person') .set((eb) => ({ - first_name: eb.bxp('first_name', `||`, '2'), + first_name: eb('first_name', '||', '2'), })) .where('first_name', '=', 'Jennifer') @@ -168,6 +287,7 @@ for (const dialect of DIALECTS) { parameters: ['2', 'Jennifer'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -175,6 +295,7 @@ for (const dialect of DIALECTS) { expect(result).to.be.instanceOf(UpdateResult) expect(result.numUpdatedRows).to.equal(1n) + expect(result.numChangedRows).to.undefined const jennifer = await ctx.db .selectFrom('person') @@ -203,6 +324,10 @@ for (const dialect of DIALECTS) { sql: 'update `person` set `last_name` = `first_name` where `first_name` = ?', parameters: ['Jennifer'], }, + mssql: { + sql: 'update "person" set "last_name" = "first_name" where "first_name" = @1', + parameters: ['Jennifer'], + }, sqlite: { sql: 'update "person" set "last_name" = "first_name" where "first_name" = ?', parameters: ['Jennifer'], @@ -213,6 +338,11 @@ for (const dialect of DIALECTS) { expect(result).to.be.instanceOf(UpdateResult) expect(result.numUpdatedRows).to.equal(1n) + if (dialect === 'mysql') { + expect(result.numChangedRows).to.equal(1n) + } else { + expect(result.numChangedRows).to.undefined + } const jennifer = await ctx.db .selectFrom('person') @@ -238,6 +368,10 @@ for (const dialect of DIALECTS) { sql: 'update `person` set `first_name` = ?, `last_name` = ? where `gender` = ?', parameters: ['Foo', 'Barson', 'female'], }, + mssql: { + sql: 'update "person" set "first_name" = @1, "last_name" = @2 where "gender" = @3', + parameters: ['Foo', 'Barson', 'female'], + }, sqlite: { sql: 'update "person" set "first_name" = ?, "last_name" = ? where "gender" = ?', parameters: ['Foo', 'Barson', 'female'], @@ -248,6 +382,11 @@ for (const dialect of DIALECTS) { expect(result).to.be.instanceOf(UpdateResult) expect(result.numUpdatedRows).to.equal(1n) + if (dialect === 'mysql') { + expect(result.numChangedRows).to.equal(1n) + } else { + expect(result.numChangedRows).to.undefined + } const female = await ctx.db .selectFrom('person') @@ -275,6 +414,7 @@ for (const dialect of DIALECTS) { parameters: ['Barson', 'male'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: 'update "person" set "last_name" = ? where "gender" = ? returning "first_name", "last_name"', parameters: ['Barson', 'male'], @@ -325,6 +465,7 @@ for (const dialect of DIALECTS) { parameters: ['Arnold'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: { sql: 'update "person" set "first_name" = "pet"."name" from "pet" where "pet"."owner_id" = "person"."id" and "person"."first_name" = ? returning "first_name"', parameters: ['Arnold'], @@ -357,9 +498,264 @@ for (const dialect of DIALECTS) { first_name, last_name: 'Nobody', gender, - })) + })), ) }) } + + if (dialect === 'mysql') { + it('should update but not change the row', async () => { + const query = ctx.db + .updateTable('person') + .set({ + first_name: 'Jennifer', + }) + .where('first_name', '=', 'Jennifer') + + await query.execute() + const result = await query.executeTakeFirst() + expect(result).instanceOf(UpdateResult) + expect(result.numUpdatedRows).to.equal(1n) + expect(result.numChangedRows).to.equal(0n) + }) + + it('should limit the amount of updated rows', async () => { + const query = ctx.db + .updateTable('person') + .set({ first_name: 'Foo' }) + .limit(2) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: { + sql: 'update `person` set `first_name` = ? limit ?', + parameters: ['Foo', 2], + }, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.executeTakeFirst() + + expect(result).to.be.instanceOf(UpdateResult) + expect(result.numUpdatedRows).to.equal(2n) + expect(result.numChangedRows).to.equal(2n) + + const people = await ctx.db + .selectFrom('person') + .select('first_name') + .where('first_name', '=', 'Foo') + .execute() + + expect(people).to.have.length(2) + }) + } + + it('should create an update query that uses a CTE', async () => { + const query = ctx.db + .with('jennifer_id', (qb) => + qb + .selectFrom('person') + .where('first_name', '=', 'Jennifer') + .$call(limit(1, dialect)) + .select('id'), + ) + .updateTable('pet') + .set((eb) => ({ + owner_id: eb.selectFrom('jennifer_id').select('id'), + })) + + testSql(query, dialect, { + postgres: { + sql: 'with "jennifer_id" as (select "id" from "person" where "first_name" = $1 limit $2) update "pet" set "owner_id" = (select "id" from "jennifer_id")', + parameters: ['Jennifer', 1], + }, + mysql: { + sql: 'with `jennifer_id` as (select `id` from `person` where `first_name` = ? limit ?) update `pet` set `owner_id` = (select `id` from `jennifer_id`)', + parameters: ['Jennifer', 1], + }, + mssql: { + sql: 'with "jennifer_id" as (select top(1) "id" from "person" where "first_name" = @1) update "pet" set "owner_id" = (select "id" from "jennifer_id")', + parameters: ['Jennifer'], + }, + sqlite: { + sql: 'with "jennifer_id" as (select "id" from "person" where "first_name" = ? limit ?) update "pet" set "owner_id" = (select "id" from "jennifer_id")', + parameters: ['Jennifer', 1], + }, + }) + + await query.execute() + + const jennifer = await ctx.db + .selectFrom('person') + .where('first_name', '=', 'Jennifer') + .select('id') + .executeTakeFirstOrThrow() + + const pets = await ctx.db.selectFrom('pet').select('owner_id').execute() + expect(pets).to.have.length(3) + + // All pets should now belong to jennifer. + for (const pet of pets) { + expect(pet.owner_id).to.equal(jennifer.id) + } + }) + + if (dialect === 'postgres') { + it('should update using a from clause and a join', async () => { + const query = ctx.db + .updateTable('pet as p') + .from('pet') + .whereRef('p.id', '=', 'pet.id') + .innerJoin('person', 'person.id', 'pet.owner_id') + .set((eb) => ({ + name: eb.fn.coalesce('person.first_name', eb.val('')), + })) + + testSql(query, dialect, { + postgres: { + sql: 'update "pet" as "p" set "name" = coalesce("person"."first_name", $1) from "pet" inner join "person" on "person"."id" = "pet"."owner_id" where "p"."id" = "pet"."id"', + parameters: [''], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + + const pets = await ctx.db + .selectFrom('pet') + .innerJoin('person', 'person.id', 'pet.owner_id') + .select(['pet.name as pet_name', 'person.first_name as person_name']) + .execute() + + expect(pets).to.have.length(3) + for (const pet of pets) { + expect(pet.person_name).to.equal(pet.pet_name) + } + }) + } + + if (dialect === 'mssql') { + it('should update using a from clause and a join', async () => { + const query = ctx.db + .updateTable('p' as 'pet') + .from('pet as p') + .innerJoin('person', 'person.id', 'p.owner_id') + .set((eb) => ({ + name: eb.fn.coalesce('person.first_name', eb.val('')), + })) + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'update "p" set "name" = coalesce("person"."first_name", @1) from "pet" as "p" inner join "person" on "person"."id" = "p"."owner_id"', + parameters: [''], + }, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + + const pets = await ctx.db + .selectFrom('pet') + .innerJoin('person', 'person.id', 'pet.owner_id') + .select(['pet.name as pet_name', 'person.first_name as person_name']) + .execute() + + expect(pets).to.have.length(3) + for (const pet of pets) { + expect(pet.person_name).to.equal(pet.pet_name) + } + }) + + it('should update top', async () => { + const query = ctx.db + .updateTable('pet') + .top(1) + .set({ name: 'Lucky' }) + .where('species', '=', 'dog') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'update top(1) "pet" set "name" = @1 where "species" = @2', + parameters: ['Lucky', 'dog'], + }, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + + it('should update top percent', async () => { + const query = ctx.db + .updateTable('pet') + .top(50, 'percent') + .set({ name: 'Lucky' }) + .where('species', '=', 'dog') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'update top(50) percent "pet" set "name" = @1 where "species" = @2', + parameters: ['Lucky', 'dog'], + }, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + } + + if (dialect === 'mssql') { + it('should update some rows and return updated rows when `output` is used', async () => { + const query = ctx.db + .updateTable('person') + .set({ last_name: 'Barson' }) + .output(['inserted.first_name', 'inserted.last_name']) + .where('gender', '=', 'male') + + testSql(query, dialect, { + postgres: NOT_SUPPORTED, + mysql: NOT_SUPPORTED, + mssql: { + sql: 'update "person" set "last_name" = @1 output "inserted"."first_name", "inserted"."last_name" where "gender" = @2', + parameters: ['Barson', 'male'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.execute() + + expect(result).to.have.length(2) + expect(Object.keys(result[0]).sort()).to.eql([ + 'first_name', + 'last_name', + ]) + expect(result).to.containSubset([ + { first_name: 'Arnold', last_name: 'Barson' }, + { first_name: 'Sylvester', last_name: 'Barson' }, + ]) + }) + + it('should update all rows, returning some fields of updated rows, and conditionally returning additional fields', async () => { + const condition = true + + const query = ctx.db + .updateTable('person') + .set({ last_name: 'Barson' }) + .output('inserted.first_name') + .$if(condition, (qb) => qb.output('inserted.last_name')) + + const result = await query.executeTakeFirstOrThrow() + + expect(result.last_name).to.equal('Barson') + }) + } }) } diff --git a/test/node/src/where.test.ts b/test/node/src/where.test.ts index 2c9a4fe81..d67a494e1 100644 --- a/test/node/src/where.test.ts +++ b/test/node/src/where.test.ts @@ -1,7 +1,6 @@ import { sql } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -9,6 +8,8 @@ import { testSql, expect, insertDefaultDataSet, + DIALECTS, + NOT_SUPPORTED, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -47,6 +48,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where `first_name` = ?', parameters: ['Arnold'], }, + mssql: { + sql: 'select * from "person" where "first_name" = @1', + parameters: ['Arnold'], + }, sqlite: { sql: 'select * from "person" where "first_name" = ?', parameters: ['Arnold'], @@ -87,6 +92,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where `last_name` is not null', parameters: [], }, + mssql: { + sql: 'select * from "person" where "last_name" is not null', + parameters: [], + }, sqlite: { sql: 'select * from "person" where "last_name" is not null', parameters: [], @@ -118,6 +127,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where `last_name` is null', parameters: [], }, + mssql: { + sql: 'select * from "person" where "last_name" is null', + parameters: [], + }, sqlite: { sql: 'select * from "person" where "last_name" is null', parameters: [], @@ -147,6 +160,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where `first_name` = ?', parameters: ['Arnold'], }, + mssql: { + sql: 'select * from "person" where "first_name" = @1', + parameters: ['Arnold'], + }, sqlite: { sql: 'select * from "person" where "first_name" = ?', parameters: ['Arnold'], @@ -180,6 +197,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where `person`.`first_name` = ?', parameters: ['Arnold'], }, + mssql: { + sql: 'select * from "person" where "person"."first_name" = @1', + parameters: ['Arnold'], + }, sqlite: { sql: 'select * from "person" where "person"."first_name" = ?', parameters: ['Arnold'], @@ -209,6 +230,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where person.first_name = ?', parameters: ['Arnold'], }, + mssql: { + sql: 'select * from "person" where person.first_name = @1', + parameters: ['Arnold'], + }, sqlite: { sql: 'select * from "person" where person.first_name = ?', parameters: ['Arnold'], @@ -234,6 +259,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where `person`.`first_name` = ?', parameters: ['Arnold'], }, + mssql: { + sql: 'select * from "person" where "person"."first_name" = @1', + parameters: ['Arnold'], + }, sqlite: { sql: 'select * from "person" where "person"."first_name" = ?', parameters: ['Arnold'], @@ -244,43 +273,50 @@ for (const dialect of DIALECTS) { expect(person!.first_name).to.equal('Arnold') }) - it('a raw instance and a boolean value', async () => { - const query = ctx.db - .selectFrom('person') - .selectAll() - .where(sql`(first_name is null)`, 'is', false) - - testSql(query, dialect, { - postgres: { - sql: 'select * from "person" where (first_name is null) is false', - parameters: [], - }, - mysql: { - sql: 'select * from `person` where (first_name is null) is false', - parameters: [], - }, - sqlite: { - sql: 'select * from "person" where (first_name is null) is false', - parameters: [], - }, + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'sqlite' + ) { + it('a raw instance and a boolean value', async () => { + const query = ctx.db + .selectFrom('person') + .selectAll() + .where(sql`(first_name is null)`, 'is', false) + + testSql(query, dialect, { + postgres: { + sql: 'select * from "person" where (first_name is null) is false', + parameters: [], + }, + mysql: { + sql: 'select * from `person` where (first_name is null) is false', + parameters: [], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'select * from "person" where (first_name is null) is false', + parameters: [], + }, + }) + + const persons = await query.execute() + expect(persons).to.have.length(3) }) - - const persons = await query.execute() - expect(persons).to.have.length(3) - }) + } it('a subquery and a primitive value', async () => { const query = ctx.db .selectFrom('person') .selectAll() .where( - (qb) => - qb + (eb) => + eb .selectFrom('pet') .select('pet.name') .whereRef('owner_id', '=', 'person.id'), '=', - 'Catto' + 'Catto', ) testSql(query, dialect, { @@ -292,6 +328,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where (select `pet`.`name` from `pet` where `owner_id` = `person`.`id`) = ?', parameters: ['Catto'], }, + mssql: { + sql: 'select * from "person" where (select "pet"."name" from "pet" where "owner_id" = "person"."id") = @1', + parameters: ['Catto'], + }, sqlite: { sql: 'select * from "person" where (select "pet"."name" from "pet" where "owner_id" = "person"."id") = ?', parameters: ['Catto'], @@ -310,15 +350,60 @@ for (const dialect of DIALECTS) { ]) }) + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'sqlite' + ) { + it('a boolean subquery', async () => { + const query = ctx.db + .selectFrom('person') + .selectAll() + .where((eb) => + eb + .selectFrom('pet') + .whereRef('owner_id', '=', 'person.id') + .select((eb) => eb('pet.name', '=', 'Doggo').as('is_doggo')), + ) + + testSql(query, dialect, { + postgres: { + sql: 'select * from "person" where (select "pet"."name" = $1 as "is_doggo" from "pet" where "owner_id" = "person"."id")', + parameters: ['Doggo'], + }, + mysql: { + sql: 'select * from `person` where (select `pet`.`name` = ? as `is_doggo` from `pet` where `owner_id` = `person`.`id`)', + parameters: ['Doggo'], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'select * from "person" where (select "pet"."name" = ? as "is_doggo" from "pet" where "owner_id" = "person"."id")', + parameters: ['Doggo'], + }, + }) + + const persons = await query.execute() + expect(persons).to.have.length(1) + expect(persons[0].id).to.be.a('number') + expect(persons).to.containSubset([ + { + first_name: 'Arnold', + last_name: 'Schwarzenegger', + gender: 'male', + }, + ]) + }) + } + it('a raw instance and a subquery', async () => { const query = ctx.db .selectFrom('person') .selectAll() - .where(sql`${'Catto'}`, '=', (qb) => - qb + .where(sql`${'Catto'}`, '=', (eb) => + eb .selectFrom('pet') .select('pet.name') - .whereRef('owner_id', '=', 'person.id') + .whereRef('owner_id', '=', 'person.id'), ) testSql(query, dialect, { @@ -330,6 +415,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where ? = (select `pet`.`name` from `pet` where `owner_id` = `person`.`id`)', parameters: ['Catto'], }, + mssql: { + sql: 'select * from "person" where @1 = (select "pet"."name" from "pet" where "owner_id" = "person"."id")', + parameters: ['Catto'], + }, sqlite: { sql: 'select * from "person" where ? = (select "pet"."name" from "pet" where "owner_id" = "person"."id")', parameters: ['Catto'], @@ -348,7 +437,7 @@ for (const dialect of DIALECTS) { const query = ctx.db .selectFrom('person') .selectAll() - .where('first_name', sql`=`, sql`${'Arnold'}`) + .where('first_name', sql`=`, sql`${'Arnold'}`) testSql(query, dialect, { postgres: { @@ -359,6 +448,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where `first_name` = ?', parameters: ['Arnold'], }, + mssql: { + sql: 'select * from "person" where "first_name" = @1', + parameters: ['Arnold'], + }, sqlite: { sql: 'select * from "person" where "first_name" = ?', parameters: ['Arnold'], @@ -393,6 +486,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where `first_name` in (?, ?) order by `first_name` desc', parameters: ['Arnold', 'Jennifer'], }, + mssql: { + sql: 'select * from "person" where "first_name" in (@1, @2) order by "first_name" desc', + parameters: ['Arnold', 'Jennifer'], + }, sqlite: { sql: 'select * from "person" where "first_name" in (?, ?) order by "first_name" desc', parameters: ['Arnold', 'Jennifer'], @@ -416,7 +513,106 @@ for (const dialect of DIALECTS) { ]) }) - it('two where clauses', async () => { + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'sqlite' + ) { + it('a `where in` query with tuples', async () => { + const query = ctx.db + .selectFrom('person') + .selectAll() + .where((eb) => + eb(eb.refTuple('first_name', 'last_name'), 'in', [ + eb.tuple('Jennifer', 'Aniston'), + eb.tuple('Sylvester', 'Stallone'), + ]), + ) + .orderBy('first_name asc') + + testSql(query, dialect, { + postgres: { + sql: 'select * from "person" where ("first_name", "last_name") in (($1, $2), ($3, $4)) order by "first_name" asc', + parameters: ['Jennifer', 'Aniston', 'Sylvester', 'Stallone'], + }, + mysql: { + sql: 'select * from `person` where (`first_name`, `last_name`) in ((?, ?), (?, ?)) order by `first_name` asc', + parameters: ['Jennifer', 'Aniston', 'Sylvester', 'Stallone'], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'select * from "person" where ("first_name", "last_name") in ((?, ?), (?, ?)) order by "first_name" asc', + parameters: ['Jennifer', 'Aniston', 'Sylvester', 'Stallone'], + }, + }) + + const persons = await query.execute() + expect(persons).to.have.length(2) + expect(persons).to.containSubset([ + { + first_name: 'Jennifer', + last_name: 'Aniston', + gender: 'female', + }, + { + first_name: 'Sylvester', + last_name: 'Stallone', + gender: 'male', + }, + ]) + }) + + it('a `where in` query with tuples and a subquery', async () => { + const query = ctx.db + .selectFrom('person') + .selectAll() + .where((eb) => + eb( + eb.refTuple('first_name', 'last_name'), + 'in', + eb + .selectFrom('person as p2') + .select(['p2.first_name', 'p2.last_name']) + .where('first_name', 'in', ['Arnold', 'Sylvester']) + .$asTuple('first_name', 'last_name'), + ), + ) + .orderBy('first_name asc') + + testSql(query, dialect, { + postgres: { + sql: 'select * from "person" where ("first_name", "last_name") in (select "p2"."first_name", "p2"."last_name" from "person" as "p2" where "first_name" in ($1, $2)) order by "first_name" asc', + parameters: ['Arnold', 'Sylvester'], + }, + mysql: { + sql: 'select * from `person` where (`first_name`, `last_name`) in (select `p2`.`first_name`, `p2`.`last_name` from `person` as `p2` where `first_name` in (?, ?)) order by `first_name` asc', + parameters: ['Arnold', 'Sylvester'], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'select * from "person" where ("first_name", "last_name") in (select "p2"."first_name", "p2"."last_name" from "person" as "p2" where "first_name" in (?, ?)) order by "first_name" asc', + parameters: ['Arnold', 'Sylvester'], + }, + }) + + const persons = await query.execute() + expect(persons).to.have.length(2) + expect(persons).to.containSubset([ + { + first_name: 'Arnold', + last_name: 'Schwarzenegger', + gender: 'male', + }, + { + first_name: 'Sylvester', + last_name: 'Stallone', + gender: 'male', + }, + ]) + }) + } + + it('two where expressions', async () => { const query = ctx.db .selectFrom('person') .selectAll() @@ -432,6 +628,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where `first_name` = ? and `person`.`last_name` = ?', parameters: ['Arnold', 'Schwarzenegger'], }, + mssql: { + sql: 'select * from "person" where "first_name" = @1 and "person"."last_name" = @2', + parameters: ['Arnold', 'Schwarzenegger'], + }, sqlite: { sql: 'select * from "person" where "first_name" = ? and "person"."last_name" = ?', parameters: ['Arnold', 'Schwarzenegger'], @@ -449,15 +649,15 @@ for (const dialect of DIALECTS) { ]) }) - it('single function argument should provide an expression builder', async () => { + it('`and where` using the expression builder', async () => { const query = ctx.db .selectFrom('person') .selectAll() - .where(({ and, cmpr, fn }) => - and([ - cmpr('first_name', '=', 'Jennifer'), - cmpr(fn('upper', ['last_name']), '=', 'ANISTON'), - ]) + .where((eb) => + eb.and([ + eb('first_name', '=', 'Jennifer'), + eb(eb.fn('upper', ['last_name']), '=', 'ANISTON'), + ]), ) testSql(query, dialect, { @@ -469,6 +669,10 @@ for (const dialect of DIALECTS) { sql: 'select * from `person` where (`first_name` = ? and upper(`last_name`) = ?)', parameters: ['Jennifer', 'ANISTON'], }, + mssql: { + sql: 'select * from "person" where ("first_name" = @1 and upper("last_name") = @2)', + parameters: ['Jennifer', 'ANISTON'], + }, sqlite: { sql: 'select * from "person" where ("first_name" = ? and upper("last_name") = ?)', parameters: ['Jennifer', 'ANISTON'], @@ -486,28 +690,34 @@ for (const dialect of DIALECTS) { ]) }) - it('single function argument should create a group', async () => { + it('`and where` using the expression builder and chaining', async () => { const query = ctx.db .selectFrom('person') .selectAll() - .where((qb) => - qb - .where('first_name', '=', 'Jennifer') - .where('last_name', '=', 'Aniston') + .where((eb) => + eb('first_name', '=', 'Jennifer').and( + eb.fn('upper', ['last_name']), + '=', + 'ANISTON', + ), ) testSql(query, dialect, { postgres: { - sql: 'select * from "person" where ("first_name" = $1 and "last_name" = $2)', - parameters: ['Jennifer', 'Aniston'], + sql: 'select * from "person" where ("first_name" = $1 and upper("last_name") = $2)', + parameters: ['Jennifer', 'ANISTON'], }, mysql: { - sql: 'select * from `person` where (`first_name` = ? and `last_name` = ?)', - parameters: ['Jennifer', 'Aniston'], + sql: 'select * from `person` where (`first_name` = ? and upper(`last_name`) = ?)', + parameters: ['Jennifer', 'ANISTON'], + }, + mssql: { + sql: 'select * from "person" where ("first_name" = @1 and upper("last_name") = @2)', + parameters: ['Jennifer', 'ANISTON'], }, sqlite: { - sql: 'select * from "person" where ("first_name" = ? and "last_name" = ?)', - parameters: ['Jennifer', 'Aniston'], + sql: 'select * from "person" where ("first_name" = ? and upper("last_name") = ?)', + parameters: ['Jennifer', 'ANISTON'], }, }) @@ -522,63 +732,73 @@ for (const dialect of DIALECTS) { ]) }) - it('single raw instance', async () => { + it('`and where` using the expression builder and a filter object', async () => { const query = ctx.db .selectFrom('person') .selectAll() - .where(sql`first_name between ${'Arnold'} and ${'Jennifer'}`) - .where(sql`last_name between ${'A'} and ${'Z'}`) + .where((eb) => + eb.and({ + first_name: 'Jennifer', + last_name: eb.fn('upper', ['first_name']), + }), + ) testSql(query, dialect, { postgres: { - sql: 'select * from "person" where first_name between $1 and $2 and last_name between $3 and $4', - parameters: ['Arnold', 'Jennifer', 'A', 'Z'], + sql: 'select * from "person" where ("first_name" = $1 and "last_name" = upper("first_name"))', + parameters: ['Jennifer'], }, mysql: { - sql: 'select * from `person` where first_name between ? and ? and last_name between ? and ?', - parameters: ['Arnold', 'Jennifer', 'A', 'Z'], + sql: 'select * from `person` where (`first_name` = ? and `last_name` = upper(`first_name`))', + parameters: ['Jennifer'], + }, + mssql: { + sql: 'select * from "person" where ("first_name" = @1 and "last_name" = upper("first_name"))', + parameters: ['Jennifer'], }, sqlite: { - sql: 'select * from "person" where first_name between ? and ? and last_name between ? and ?', - parameters: ['Arnold', 'Jennifer', 'A', 'Z'], + sql: 'select * from "person" where ("first_name" = ? and "last_name" = upper("first_name"))', + parameters: ['Jennifer'], }, }) - await query.execute() + const persons = await query.execute() + expect(persons).to.have.length(0) }) - }) - describe('orWhere', () => { - it('two where clauses', async () => { + it('`or where` using the expression builder', async () => { const query = ctx.db .selectFrom('person') .selectAll() - .where('first_name', '=', 'Arnold') - .orWhere('first_name', '=', 'Jennifer') + .where(({ or, eb }) => + or([ + eb('first_name', '=', 'Jennifer'), + eb(eb.fn('upper', ['last_name']), '=', 'ANISTON'), + ]), + ) testSql(query, dialect, { postgres: { - sql: 'select * from "person" where "first_name" = $1 or "first_name" = $2', - parameters: ['Arnold', 'Jennifer'], + sql: 'select * from "person" where ("first_name" = $1 or upper("last_name") = $2)', + parameters: ['Jennifer', 'ANISTON'], }, mysql: { - sql: 'select * from `person` where `first_name` = ? or `first_name` = ?', - parameters: ['Arnold', 'Jennifer'], + sql: 'select * from `person` where (`first_name` = ? or upper(`last_name`) = ?)', + parameters: ['Jennifer', 'ANISTON'], + }, + mssql: { + sql: 'select * from "person" where ("first_name" = @1 or upper("last_name") = @2)', + parameters: ['Jennifer', 'ANISTON'], }, sqlite: { - sql: 'select * from "person" where "first_name" = ? or "first_name" = ?', - parameters: ['Arnold', 'Jennifer'], + sql: 'select * from "person" where ("first_name" = ? or upper("last_name") = ?)', + parameters: ['Jennifer', 'ANISTON'], }, }) const persons = await query.execute() - expect(persons).to.have.length(2) + expect(persons).to.have.length(1) expect(persons).to.containSubset([ - { - first_name: 'Arnold', - last_name: 'Schwarzenegger', - gender: 'male', - }, { first_name: 'Jennifer', last_name: 'Aniston', @@ -587,40 +807,40 @@ for (const dialect of DIALECTS) { ]) }) - it('two where clause groups', async () => { + it('`or where` using the expression builder and chaining', async () => { const query = ctx.db .selectFrom('person') .selectAll() - .where('first_name', '=', 'Arnold') - .orWhere((qb) => - qb - .where('first_name', '=', 'Jennifer') - .where('last_name', '=', 'Aniston') + .where((eb) => + eb('first_name', '=', 'Jennifer').or( + eb.fn('upper', ['last_name']), + '=', + 'ANISTON', + ), ) testSql(query, dialect, { postgres: { - sql: 'select * from "person" where "first_name" = $1 or ("first_name" = $2 and "last_name" = $3)', - parameters: ['Arnold', 'Jennifer', 'Aniston'], + sql: 'select * from "person" where ("first_name" = $1 or upper("last_name") = $2)', + parameters: ['Jennifer', 'ANISTON'], }, mysql: { - sql: 'select * from `person` where `first_name` = ? or (`first_name` = ? and `last_name` = ?)', - parameters: ['Arnold', 'Jennifer', 'Aniston'], + sql: 'select * from `person` where (`first_name` = ? or upper(`last_name`) = ?)', + parameters: ['Jennifer', 'ANISTON'], + }, + mssql: { + sql: 'select * from "person" where ("first_name" = @1 or upper("last_name") = @2)', + parameters: ['Jennifer', 'ANISTON'], }, sqlite: { - sql: 'select * from "person" where "first_name" = ? or ("first_name" = ? and "last_name" = ?)', - parameters: ['Arnold', 'Jennifer', 'Aniston'], + sql: 'select * from "person" where ("first_name" = ? or upper("last_name") = ?)', + parameters: ['Jennifer', 'ANISTON'], }, }) const persons = await query.execute() - expect(persons).to.have.length(2) + expect(persons).to.have.length(1) expect(persons).to.containSubset([ - { - first_name: 'Arnold', - last_name: 'Schwarzenegger', - gender: 'male', - }, { first_name: 'Jennifer', last_name: 'Aniston', @@ -629,302 +849,228 @@ for (const dialect of DIALECTS) { ]) }) - it('single raw instance', async () => { + it('subquery exists', async () => { const query = ctx.db .selectFrom('person') .selectAll() - .where((qb) => - qb - .where(sql`first_name between ${'Arnold'} and ${'Jennifer'}`) - .orWhere(sql`last_name between ${'A'} and ${'Z'}`) + .where(({ exists, selectFrom, lit }) => + exists( + selectFrom('pet') + .select(lit(1).as('exists')) + .whereRef('pet.owner_id', '=', 'person.id'), + ), ) testSql(query, dialect, { postgres: { - sql: 'select * from "person" where (first_name between $1 and $2 or last_name between $3 and $4)', - parameters: ['Arnold', 'Jennifer', 'A', 'Z'], + sql: 'select * from "person" where exists (select 1 as "exists" from "pet" where "pet"."owner_id" = "person"."id")', + parameters: [], }, mysql: { - sql: 'select * from `person` where (first_name between ? and ? or last_name between ? and ?)', - parameters: ['Arnold', 'Jennifer', 'A', 'Z'], - }, - sqlite: { - sql: 'select * from "person" where (first_name between ? and ? or last_name between ? and ?)', - parameters: ['Arnold', 'Jennifer', 'A', 'Z'], - }, - }) - - await query.execute() - }) - }) - - describe('whereRef', () => { - it('should compare two columns', async () => { - const query = ctx.db - .selectFrom(['person', 'pet']) - .selectAll() - .whereRef('person.id', '=', 'pet.id') - - testSql(query, dialect, { - postgres: { - sql: 'select * from "person", "pet" where "person"."id" = "pet"."id"', + sql: 'select * from `person` where exists (select 1 as `exists` from `pet` where `pet`.`owner_id` = `person`.`id`)', parameters: [], }, - mysql: { - sql: 'select * from `person`, `pet` where `person`.`id` = `pet`.`id`', + mssql: { + sql: 'select * from "person" where exists (select 1 as "exists" from "pet" where "pet"."owner_id" = "person"."id")', parameters: [], }, sqlite: { - sql: 'select * from "person", "pet" where "person"."id" = "pet"."id"', + sql: 'select * from "person" where exists (select 1 as "exists" from "pet" where "pet"."owner_id" = "person"."id")', parameters: [], }, }) + + const persons = await query.execute() + expect(persons).to.have.length(3) }) - }) - describe('orWhereRef', () => { - it('should compare two columns', async () => { + it('subquery not exists', async () => { const query = ctx.db - .selectFrom(['person', 'pet']) + .selectFrom('person') .selectAll() - .where((qb) => - qb - .whereRef('person.id', '=', 'pet.id') - .orWhereRef('person.first_name', '=', 'pet.name') + .where(({ not, exists, selectFrom }) => + not( + exists( + selectFrom('pet') + .select('pet.id') + .whereRef('pet.owner_id', '=', 'person.id'), + ), + ), ) testSql(query, dialect, { postgres: { - sql: 'select * from "person", "pet" where ("person"."id" = "pet"."id" or "person"."first_name" = "pet"."name")', + sql: 'select * from "person" where not exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id")', parameters: [], }, mysql: { - sql: 'select * from `person`, `pet` where (`person`.`id` = `pet`.`id` or `person`.`first_name` = `pet`.`name`)', + sql: 'select * from `person` where not exists (select `pet`.`id` from `pet` where `pet`.`owner_id` = `person`.`id`)', parameters: [], }, - sqlite: { - sql: 'select * from "person", "pet" where ("person"."id" = "pet"."id" or "person"."first_name" = "pet"."name")', + mssql: { + sql: 'select * from "person" where not exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id")', parameters: [], }, - }) - }) - }) - - describe('whereExists', () => { - it('should accept a subquery', async () => { - const query = ctx.db - .selectFrom('person') - .selectAll() - .whereExists((qb) => - qb - .selectFrom('pet') - .select('pet.id') - .whereRef('pet.owner_id', '=', 'person.id') - .where('pet.species', '=', 'dog') - ) - - testSql(query, dialect, { - postgres: { - sql: `select * from "person" where exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id" and "pet"."species" = $1)`, - parameters: ['dog'], - }, - mysql: { - sql: 'select * from `person` where exists (select `pet`.`id` from `pet` where `pet`.`owner_id` = `person`.`id` and `pet`.`species` = ?)', - parameters: ['dog'], - }, sqlite: { - sql: `select * from "person" where exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id" and "pet"."species" = ?)`, - parameters: ['dog'], + sql: 'select * from "person" where not exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id")', + parameters: [], }, }) const persons = await query.execute() - expect(persons).to.have.length(1) - expect(persons).to.containSubset([ - { - first_name: 'Arnold', - last_name: 'Schwarzenegger', - gender: 'male', - }, - ]) + expect(persons).to.have.length(0) }) - it('should accept a raw instance', async () => { - const query = ctx.db - .selectFrom('person') - .selectAll() - .whereExists( - sql`(select ${sql.ref('pet.id')} from ${sql.ref( - 'pet' - )} where ${sql.ref('pet.owner_id')} = ${sql.ref( - 'person.id' - )} and ${sql.ref('pet.species')} = ${'cat'})` - ) - - testSql(query, dialect, { - postgres: { - sql: `select * from "person" where exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id" and "pet"."species" = $1)`, - parameters: ['cat'], - }, - mysql: { - sql: 'select * from `person` where exists (select `pet`.`id` from `pet` where `pet`.`owner_id` = `person`.`id` and `pet`.`species` = ?)', - parameters: ['cat'], - }, - sqlite: { - sql: `select * from "person" where exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id" and "pet"."species" = ?)`, - parameters: ['cat'], - }, + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'sqlite' + ) { + it('case expression', async () => { + const query = ctx.db + .selectFrom('person') + .selectAll() + .where((eb) => + eb + .case() + .when('first_name', '=', 'Jennifer') + .then(sql.lit(true)) + .else(sql.lit(false)) + .end(), + ) + + testSql(query, dialect, { + postgres: { + sql: 'select * from "person" where case when "first_name" = $1 then true else false end', + parameters: ['Jennifer'], + }, + mysql: { + sql: 'select * from `person` where case when `first_name` = ? then true else false end', + parameters: ['Jennifer'], + }, + mssql: NOT_SUPPORTED, + sqlite: { + sql: 'select * from "person" where case when "first_name" = ? then true else false end', + parameters: ['Jennifer'], + }, + }) + + const persons = await query.execute() + expect(persons).to.have.length(1) }) + } - const persons = await query.execute() - expect(persons).to.have.length(1) - expect(persons).to.containSubset([ - { - first_name: 'Jennifer', - last_name: 'Aniston', - gender: 'female', - }, - ]) - }) - }) - - describe('orWhereExists', () => { - it('should accept a subquery', async () => { + it('single raw instance', async () => { const query = ctx.db .selectFrom('person') .selectAll() - .where((qb) => - qb - .where('first_name', '=', 'Jennifer') - .orWhereExists((qb) => - qb - .selectFrom('pet') - .select('pet.id') - .whereRef('pet.owner_id', '=', 'person.id') - .where('pet.species', '=', 'hamster') - ) - ) + .where(sql`first_name between ${'Arnold'} and ${'Jennifer'}`) + .where(sql`last_name between ${'A'} and ${'Z'}`) testSql(query, dialect, { postgres: { - sql: `select * from "person" where ("first_name" = $1 or exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id" and "pet"."species" = $2))`, - parameters: ['Jennifer', 'hamster'], + sql: 'select * from "person" where first_name between $1 and $2 and last_name between $3 and $4', + parameters: ['Arnold', 'Jennifer', 'A', 'Z'], }, mysql: { - sql: 'select * from `person` where (`first_name` = ? or exists (select `pet`.`id` from `pet` where `pet`.`owner_id` = `person`.`id` and `pet`.`species` = ?))', - parameters: ['Jennifer', 'hamster'], + sql: 'select * from `person` where first_name between ? and ? and last_name between ? and ?', + parameters: ['Arnold', 'Jennifer', 'A', 'Z'], + }, + mssql: { + sql: 'select * from "person" where first_name between @1 and @2 and last_name between @3 and @4', + parameters: ['Arnold', 'Jennifer', 'A', 'Z'], }, sqlite: { - sql: `select * from "person" where ("first_name" = ? or exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id" and "pet"."species" = ?))`, - parameters: ['Jennifer', 'hamster'], + sql: 'select * from "person" where first_name between ? and ? and last_name between ? and ?', + parameters: ['Arnold', 'Jennifer', 'A', 'Z'], }, }) - const persons = await query.execute() - expect(persons).to.have.length(2) - expect(persons).to.containSubset([ - { - first_name: 'Sylvester', - last_name: 'Stallone', - gender: 'male', - }, - { - first_name: 'Jennifer', - last_name: 'Aniston', - gender: 'female', - }, - ]) + await query.execute() }) - }) - - describe('whereNotExists', () => { - it('should accept a subquery', async () => { - const query = ctx.db - .selectFrom('person') - .selectAll() - .whereNotExists((qb) => - qb - .selectFrom('pet') - .select('pet.id') - .whereRef('pet.owner_id', '=', 'person.id') - .where('pet.species', '=', 'dog') - ) - testSql(query, dialect, { - postgres: { - sql: `select * from "person" where not exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id" and "pet"."species" = $1)`, - parameters: ['dog'], - }, - mysql: { - sql: 'select * from `person` where not exists (select `pet`.`id` from `pet` where `pet`.`owner_id` = `person`.`id` and `pet`.`species` = ?)', - parameters: ['dog'], - }, - sqlite: { - sql: `select * from "person" where not exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id" and "pet"."species" = ?)`, - parameters: ['dog'], - }, + if ( + dialect === 'postgres' || + dialect === 'mysql' || + dialect === 'mssql' + ) { + it('subquery inside `any` operator', async () => { + await ctx.db + .insertInto('pet') + .values((eb) => ({ + name: 'Cat Stevens', + species: 'cat', + owner_id: eb + .selectFrom('person') + .select('id') + .where('first_name', '=', 'Jennifer'), + })) + .execute() + + const query = ctx.db + .selectFrom('person') + .select('first_name') + .where((eb) => + eb( + eb.val('Cat Stevens'), + '=', + eb.fn.any( + eb + .selectFrom('pet') + .whereRef('pet.owner_id', '=', 'person.id') + .select('name'), + ), + ), + ) + + testSql(query, dialect, { + postgres: { + sql: 'select "first_name" from "person" where $1 = any((select "name" from "pet" where "pet"."owner_id" = "person"."id"))', + parameters: ['Cat Stevens'], + }, + mysql: { + sql: 'select `first_name` from `person` where ? = any((select `name` from `pet` where `pet`.`owner_id` = `person`.`id`))', + parameters: ['Cat Stevens'], + }, + mssql: { + sql: 'select "first_name" from "person" where @1 = any((select "name" from "pet" where "pet"."owner_id" = "person"."id"))', + parameters: ['Cat Stevens'], + }, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.execute() + expect(result).to.have.length(1) + expect(result[0]).to.eql({ first_name: 'Jennifer' }) }) - - const persons = await query.execute() - expect(persons).to.have.length(2) - expect(persons).to.containSubset([ - { - first_name: 'Sylvester', - last_name: 'Stallone', - gender: 'male', - }, - { - first_name: 'Jennifer', - last_name: 'Aniston', - gender: 'female', - }, - ]) - }) + } }) - describe('orWhereNotExists', () => { - it('should accept a subquery', async () => { + describe('whereRef', () => { + it('should compare two columns', async () => { const query = ctx.db - .selectFrom('person') + .selectFrom(['person', 'pet']) .selectAll() - .where('first_name', 'is', null) - .orWhereNotExists((qb) => - qb - .selectFrom('pet') - .select('pet.id') - .whereRef('pet.owner_id', '=', 'person.id') - .where('pet.species', '=', 'hamster') - ) + .whereRef('person.id', '=', 'pet.id') testSql(query, dialect, { postgres: { - sql: `select * from "person" where "first_name" is null or not exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id" and "pet"."species" = $1)`, - parameters: ['hamster'], + sql: 'select * from "person", "pet" where "person"."id" = "pet"."id"', + parameters: [], }, mysql: { - sql: 'select * from `person` where `first_name` is null or not exists (select `pet`.`id` from `pet` where `pet`.`owner_id` = `person`.`id` and `pet`.`species` = ?)', - parameters: ['hamster'], + sql: 'select * from `person`, `pet` where `person`.`id` = `pet`.`id`', + parameters: [], + }, + mssql: { + sql: 'select * from "person", "pet" where "person"."id" = "pet"."id"', + parameters: [], }, sqlite: { - sql: `select * from "person" where "first_name" is null or not exists (select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id" and "pet"."species" = ?)`, - parameters: ['hamster'], + sql: 'select * from "person", "pet" where "person"."id" = "pet"."id"', + parameters: [], }, }) - - const persons = await query.execute() - expect(persons).to.have.length(2) - expect(persons).to.containSubset([ - { - first_name: 'Arnold', - last_name: 'Schwarzenegger', - gender: 'male', - }, - { - first_name: 'Jennifer', - last_name: 'Aniston', - gender: 'female', - }, - ]) }) }) }) diff --git a/test/node/src/with-schema.test.ts b/test/node/src/with-schema.test.ts index 0302aefb3..ad9556d5c 100644 --- a/test/node/src/with-schema.test.ts +++ b/test/node/src/with-schema.test.ts @@ -7,38 +7,38 @@ import { NOT_SUPPORTED, createTableWithId, DIALECTS, + insert, + limit, } from './test-setup.js' -if (DIALECTS.includes('postgres')) { - const dialect = 'postgres' as const - +for (const dialect of DIALECTS.filter( + (dialect) => dialect === 'postgres' || dialect === 'mssql', +)) { describe(`${dialect}: with schema`, () => { let ctx: TestContext before(async function () { ctx = await initTest(this, dialect) - await dropTables() await createTables() }) beforeEach(async () => { - const person = await ctx.db - .insertInto('person') - .values({ + const personId = await insert( + ctx, + ctx.db.insertInto('person').values({ first_name: 'Foo', last_name: 'Bar', gender: 'other', - }) - .returning('id') - .executeTakeFirst() + }), + ) await ctx.db .withSchema('mammals') .insertInto('pet') .values({ name: 'Catto', - owner_id: person!.id, + owner_id: personId, species: 'cat', }) .execute() @@ -64,6 +64,10 @@ if (DIALECTS.includes('postgres')) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'select * from "mammals"."pet"', + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -83,6 +87,10 @@ if (DIALECTS.includes('postgres')) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'select * from "mammals"."pet" as "p" left join "mammals"."pet" on "mammals"."pet"."id" = "p"."id"', + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -102,6 +110,10 @@ if (DIALECTS.includes('postgres')) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'select * from "mammals"."pet" as "p1" left join "mammals"."pet" as "p2" on "p1"."id" = "p2"."id"', + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -120,6 +132,10 @@ if (DIALECTS.includes('postgres')) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'select "p"."name" from "mammals"."pet" as "p"', + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -150,6 +166,14 @@ if (DIALECTS.includes('postgres')) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: [ + 'select "mammals"."pet"."name",', + '(select "name" from "mammals"."pet" as "p" where "p"."id" = "mammals"."pet"."id") as "p_name"', + 'from "mammals"."pet"', + ], + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -164,7 +188,7 @@ if (DIALECTS.includes('postgres')) { 'pet.name', (qb) => qb - .withSchema('public') + .withSchema(dialect === 'postgres' ? 'public' : 'dbo') .selectFrom('person') .select('first_name') .whereRef('pet.owner_id', '=', 'person.id') @@ -181,6 +205,14 @@ if (DIALECTS.includes('postgres')) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: [ + 'select "mammals"."pet"."name",', + '(select "first_name" from "dbo"."person" where "mammals"."pet"."owner_id" = "dbo"."person"."id") as "owner_first_name"', + 'from "mammals"."pet"', + ], + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -193,7 +225,7 @@ if (DIALECTS.includes('postgres')) { const [anyPerson] = await ctx.db .selectFrom('person') .selectAll() - .limit(1) + .$call(limit(1, dialect)) .execute() const query = ctx.db @@ -204,7 +236,7 @@ if (DIALECTS.includes('postgres')) { species: 'dog', owner_id: anyPerson.id, }) - .returning('pet.id') + .$call((qb) => (dialect === 'postgres' ? qb.returning('pet.id') : qb)) testSql(query, dialect, { postgres: { @@ -212,11 +244,14 @@ if (DIALECTS.includes('postgres')) { parameters: ['Doggo', 'dog', anyPerson.id], }, mysql: NOT_SUPPORTED, - sqlite: { - sql: 'insert into "mammals"."pet" ("name", "species", "owner_id") values (?, ?, ?) returning "mammals"."pet"."id"', + mssql: { + sql: 'insert into "mammals"."pet" ("name", "species", "owner_id") values (@1, @2, @3)', parameters: ['Doggo', 'dog', anyPerson.id], }, + sqlite: NOT_SUPPORTED, }) + + await query.execute() }) }) @@ -233,6 +268,10 @@ if (DIALECTS.includes('postgres')) { parameters: ['Doggo'], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'delete from "mammals"."pet" where "mammals"."pet"."name" = @1', + parameters: ['Doggo'], + }, sqlite: NOT_SUPPORTED, }) @@ -254,6 +293,10 @@ if (DIALECTS.includes('postgres')) { parameters: ['cat', 'Doggo'], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'update "mammals"."pet" set "species" = @1 where "mammals"."pet"."name" = @2', + parameters: ['cat', 'Doggo'], + }, sqlite: NOT_SUPPORTED, }) @@ -266,7 +309,7 @@ if (DIALECTS.includes('postgres')) { const query = ctx.db .withSchema('mammals') .with('doggo', (db) => - db.selectFrom('pet').where('pet.name', '=', 'Doggo').selectAll() + db.selectFrom('pet').where('pet.name', '=', 'Doggo').selectAll(), ) .selectFrom('doggo') .selectAll() @@ -277,53 +320,71 @@ if (DIALECTS.includes('postgres')) { parameters: ['Doggo'], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'with "doggo" as (select * from "mammals"."pet" where "mammals"."pet"."name" = @1) select * from "doggo"', + parameters: ['Doggo'], + }, sqlite: NOT_SUPPORTED, }) await query.execute() }) - }) - describe('create table', () => { - it('should add schema for references', async () => { - const query = ctx.db.schema + it('should not add schema for common table expression names in subqueries', async () => { + const query = ctx.db .withSchema('mammals') - .createTable('foo') - .addColumn('bar', 'integer', (col) => col.references('pets.id')) + .with('doggo', (qb) => + qb.selectFrom('pet').where('name', '=', 'Doggo').select('pet.id'), + ) + .selectFrom('pet') + .select((eb) => [ + 'pet.id', + eb.selectFrom('doggo').select('id').as('doggo_id'), + ]) + .selectAll() testSql(query, dialect, { postgres: { - sql: 'create table "mammals"."foo" ("bar" integer references "mammals"."pets" ("id"))', - parameters: [], + sql: 'with "doggo" as (select "mammals"."pet"."id" from "mammals"."pet" where "name" = $1) select "mammals"."pet"."id", (select "id" from "doggo") as "doggo_id", * from "mammals"."pet"', + parameters: ['Doggo'], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'with "doggo" as (select "mammals"."pet"."id" from "mammals"."pet" where "name" = @1) select "mammals"."pet"."id", (select "id" from "doggo") as "doggo_id", * from "mammals"."pet"', + parameters: ['Doggo'], + }, sqlite: NOT_SUPPORTED, }) + + await query.execute() }) }) - describe('create index', () => { + describe('create table', () => { afterEach(async () => { await ctx.db.schema .withSchema('mammals') - .dropIndex('pet_id_index') + .dropTable('foo') .ifExists() .execute() }) - it('should not add schema for created index', async () => { + it('should add schema for references', async () => { const query = ctx.db.schema .withSchema('mammals') - .createIndex('pet_id_index') - .column('id') - .on('pet') + .createTable('foo') + .addColumn('bar', 'integer', (col) => col.references('pet.id')) testSql(query, dialect, { postgres: { - sql: 'create index "pet_id_index" on "mammals"."pet" ("id")', + sql: 'create table "mammals"."foo" ("bar" integer references "mammals"."pet" ("id"))', parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'create table "mammals"."foo" ("bar" integer references "mammals"."pet" ("id"))', + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -331,16 +392,7 @@ if (DIALECTS.includes('postgres')) { }) }) - describe('drop index', () => { - beforeEach(async () => { - await ctx.db.schema - .withSchema('mammals') - .createIndex('pet_id_index') - .column('id') - .on('pet') - .execute() - }) - + describe('create index', () => { afterEach(async () => { await ctx.db.schema .withSchema('mammals') @@ -349,17 +401,23 @@ if (DIALECTS.includes('postgres')) { .execute() }) - it('should add schema for dropped index', async () => { + it('should not add schema for created index', async () => { const query = ctx.db.schema .withSchema('mammals') - .dropIndex('pet_id_index') + .createIndex('pet_id_index') + .column('id') + .on('pet') testSql(query, dialect, { postgres: { - sql: 'drop index "mammals"."pet_id_index"', + sql: 'create index "pet_id_index" on "mammals"."pet" ("id")', parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: 'create index "pet_id_index" on "mammals"."pet" ("id")', + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -367,6 +425,37 @@ if (DIALECTS.includes('postgres')) { }) }) + if (dialect === 'postgres') { + describe('drop index', () => { + beforeEach(async () => { + await ctx.db.schema + .withSchema('mammals') + .createIndex('pet_id_index') + .column('id') + .on('pet') + .execute() + }) + + it('should add schema for dropped index', async () => { + const query = ctx.db.schema + .withSchema('mammals') + .dropIndex('pet_id_index') + + testSql(query, dialect, { + postgres: { + sql: 'drop index "mammals"."pet_id_index"', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + await query.execute() + }) + }) + } + describe('create view', () => { afterEach(async () => { await ctx.db.schema @@ -380,14 +469,18 @@ if (DIALECTS.includes('postgres')) { const query = ctx.db.schema .withSchema('mammals') .createView('dogs') - .as(ctx.db.selectFrom('pet').where('species', '=', 'dog')) + .as(ctx.db.selectFrom('pet').where('species', '=', 'dog').selectAll()) testSql(query, dialect, { postgres: { - sql: `create view "mammals"."dogs" as select from "mammals"."pet" where "species" = 'dog'`, + sql: `create view "mammals"."dogs" as select * from "mammals"."pet" where "species" = 'dog'`, parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: `create view "mammals"."dogs" as select * from "mammals"."pet" where "species" = 'dog'`, + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -400,15 +493,7 @@ if (DIALECTS.includes('postgres')) { await ctx.db.schema .withSchema('mammals') .createView('dogs') - .as(ctx.db.selectFrom('pet').where('species', '=', 'dog')) - .execute() - }) - - afterEach(async () => { - await ctx.db.schema - .withSchema('mammals') - .dropView('dogs') - .ifExists() + .as(ctx.db.selectFrom('pet').where('species', '=', 'dog').selectAll()) .execute() }) @@ -421,6 +506,10 @@ if (DIALECTS.includes('postgres')) { parameters: [], }, mysql: NOT_SUPPORTED, + mssql: { + sql: `drop view "mammals"."dogs"`, + parameters: [], + }, sqlite: NOT_SUPPORTED, }) @@ -429,20 +518,27 @@ if (DIALECTS.includes('postgres')) { }) async function createTables(): Promise { - await ctx.db.schema.createSchema('mammals').ifNotExists().execute() + await ctx.db.schema + .createSchema('mammals') + .$call((qb) => (dialect === 'postgres' ? qb.ifNotExists() : qb)) + .execute() const table = createTableWithId( ctx.db.schema.withSchema('mammals'), dialect, - 'pet' + 'pet', ) await table - .addColumn('name', 'varchar', (col) => col.unique()) + .addColumn('name', 'varchar(50)', (col) => col.unique()) .addColumn('owner_id', 'integer', (col) => - col.references('public.person.id').onDelete('cascade') + col + .references( + dialect === 'postgres' ? 'public.person.id' : 'dbo.person.id', + ) + .onDelete('cascade'), ) - .addColumn('species', 'varchar') + .addColumn('species', 'varchar(50)') .execute() } diff --git a/test/node/src/with.test.ts b/test/node/src/with.test.ts index 10090f754..d51520814 100644 --- a/test/node/src/with.test.ts +++ b/test/node/src/with.test.ts @@ -1,7 +1,6 @@ import { sql } from '../../../' import { - DIALECTS, clearDatabase, destroyTest, initTest, @@ -10,6 +9,7 @@ import { expect, NOT_SUPPORTED, insertDefaultDataSet, + DIALECTS, } from './test-setup.js' for (const dialect of DIALECTS) { @@ -37,35 +37,44 @@ for (const dialect of DIALECTS) { .with('jennifer_and_sylvester', (db) => db .selectFrom('person') - .where('first_name', '=', 'Jennifer') - .orWhere('first_name', '=', 'Sylvester') - .select(['id', 'first_name', 'gender']) + .where((eb) => + eb.or([ + eb('first_name', '=', 'Jennifer'), + eb('first_name', '=', 'Sylvester'), + ]), + ) + .select(['id', 'first_name', 'gender']), ) .with('sylvester', (db) => db .selectFrom('jennifer_and_sylvester') .where('gender', '=', 'male') - .selectAll() + .selectAll(), ) .selectFrom('sylvester') .selectAll() testSql(query, dialect, { postgres: { - sql: 'with "jennifer_and_sylvester" as (select "id", "first_name", "gender" from "person" where "first_name" = $1 or "first_name" = $2), "sylvester" as (select * from "jennifer_and_sylvester" where "gender" = $3) select * from "sylvester"', + sql: 'with "jennifer_and_sylvester" as (select "id", "first_name", "gender" from "person" where ("first_name" = $1 or "first_name" = $2)), "sylvester" as (select * from "jennifer_and_sylvester" where "gender" = $3) select * from "sylvester"', parameters: ['Jennifer', 'Sylvester', 'male'], }, mysql: { - sql: 'with `jennifer_and_sylvester` as (select `id`, `first_name`, `gender` from `person` where `first_name` = ? or `first_name` = ?), `sylvester` as (select * from `jennifer_and_sylvester` where `gender` = ?) select * from `sylvester`', + sql: 'with `jennifer_and_sylvester` as (select `id`, `first_name`, `gender` from `person` where (`first_name` = ? or `first_name` = ?)), `sylvester` as (select * from `jennifer_and_sylvester` where `gender` = ?) select * from `sylvester`', + parameters: ['Jennifer', 'Sylvester', 'male'], + }, + mssql: { + sql: 'with "jennifer_and_sylvester" as (select "id", "first_name", "gender" from "person" where ("first_name" = @1 or "first_name" = @2)), "sylvester" as (select * from "jennifer_and_sylvester" where "gender" = @3) select * from "sylvester"', parameters: ['Jennifer', 'Sylvester', 'male'], }, sqlite: { - sql: 'with "jennifer_and_sylvester" as (select "id", "first_name", "gender" from "person" where "first_name" = ? or "first_name" = ?), "sylvester" as (select * from "jennifer_and_sylvester" where "gender" = ?) select * from "sylvester"', + sql: 'with "jennifer_and_sylvester" as (select "id", "first_name", "gender" from "person" where ("first_name" = ? or "first_name" = ?)), "sylvester" as (select * from "jennifer_and_sylvester" where "gender" = ?) select * from "sylvester"', parameters: ['Jennifer', 'Sylvester', 'male'], }, }) const result = await query.execute() + expect(result).to.have.length(1) expect(Object.keys(result[0]).sort()).to.eql([ 'first_name', @@ -84,7 +93,7 @@ for (const dialect of DIALECTS) { db .selectFrom('person') .where('first_name', '=', 'Arnold') - .select(['id', 'first_name']) + .select(['id', 'first_name']), ) .selectFrom('arnold') .selectAll() @@ -98,6 +107,10 @@ for (const dialect of DIALECTS) { sql: 'with `arnold`(`id`, `first_name`) as (select `id`, `first_name` from `person` where `first_name` = ?) select * from `arnold`', parameters: ['Arnold'], }, + mssql: { + sql: 'with "arnold"("id", "first_name") as (select "id", "first_name" from "person" where "first_name" = @1) select * from "arnold"', + parameters: ['Arnold'], + }, sqlite: { sql: 'with "arnold"("id", "first_name") as (select "id", "first_name" from "person" where "first_name" = ?) select * from "arnold"', parameters: ['Arnold'], @@ -116,7 +129,7 @@ for (const dialect of DIALECTS) { .temporary() .addColumn('name', 'varchar', (col) => col.notNull().unique()) .addColumn('parent', 'varchar', (col) => - col.references('node.name') + col.references('node.name'), ) .onCommit('drop') .execute() @@ -150,8 +163,8 @@ for (const dialect of DIALECTS) { db .selectFrom('node') .innerJoin('ancestors', 'node.name', 'ancestors.parent') - .select(['node.name', 'node.parent']) - ) + .select(['node.name', 'node.parent']), + ), ) .selectFrom('ancestors') .select('name') @@ -162,6 +175,7 @@ for (const dialect of DIALECTS) { parameters: ['node1'], }, mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, }) @@ -174,16 +188,72 @@ for (const dialect of DIALECTS) { ]) }) }) + + it('should create a CTE with `as materialized`', async () => { + const query = ctx.db + .with( + (cte) => cte('person_name').materialized(), + (qb) => qb.selectFrom('person').select('first_name'), + ) + .selectFrom('person_name') + .select('person_name.first_name') + .orderBy('first_name') + + testSql(query, dialect, { + postgres: { + sql: 'with "person_name" as materialized (select "first_name" from "person") select "person_name"."first_name" from "person_name" order by "first_name"', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.execute() + expect(result).to.eql([ + { first_name: 'Arnold' }, + { first_name: 'Jennifer' }, + { first_name: 'Sylvester' }, + ]) + }) + + it('should create a CTE with `as not materialized`', async () => { + const query = ctx.db + .with( + (cte) => cte('person_name').notMaterialized(), + (qb) => qb.selectFrom('person').select('first_name'), + ) + .selectFrom('person_name') + .select('person_name.first_name') + .orderBy('first_name') + + testSql(query, dialect, { + postgres: { + sql: 'with "person_name" as not materialized (select "first_name" from "person") select "person_name"."first_name" from "person_name" order by "first_name"', + parameters: [], + }, + mysql: NOT_SUPPORTED, + mssql: NOT_SUPPORTED, + sqlite: NOT_SUPPORTED, + }) + + const result = await query.execute() + expect(result).to.eql([ + { first_name: 'Arnold' }, + { first_name: 'Jennifer' }, + { first_name: 'Sylvester' }, + ]) + }) } - if (dialect !== 'mysql') { + if (dialect === 'postgres' || dialect === 'mssql' || dialect === 'sqlite') { it('should create an insert query with common table expressions', async () => { const query = ctx.db .with('jennifer', (db) => db .selectFrom('person') .where('first_name', '=', 'Jennifer') - .select(['id', 'first_name', 'gender']) + .select(['id', 'first_name', 'gender']), ) .insertInto('pet') .values({ @@ -197,6 +267,10 @@ for (const dialect of DIALECTS) { sql: 'with "jennifer" as (select "id", "first_name", "gender" from "person" where "first_name" = $1) insert into "pet" ("owner_id", "name", "species") values ((select "id" from "jennifer"), $2, $3)', parameters: ['Jennifer', 'Catto 2', 'cat'], }, + mssql: { + sql: 'with "jennifer" as (select "id", "first_name", "gender" from "person" where "first_name" = @1) insert into "pet" ("owner_id", "name", "species") values ((select "id" from "jennifer"), @2, @3)', + parameters: ['Jennifer', 'Catto 2', 'cat'], + }, sqlite: { sql: 'with "jennifer" as (select "id", "first_name", "gender" from "person" where "first_name" = ?) insert into "pet" ("owner_id", "name", "species") values ((select "id" from "jennifer"), ?, ?)', parameters: ['Jennifer', 'Catto 2', 'cat'], @@ -208,14 +282,14 @@ for (const dialect of DIALECTS) { }) } - if (dialect !== 'mysql' && dialect !== 'sqlite') { + if (dialect === 'postgres') { it('should create a with query where CTEs are inserts updates and deletes', async () => { const query = ctx.db .with('deleted_arnold', (db) => db .deleteFrom('person') .where('first_name', '=', 'Arnold') - .returning('first_name as deleted_first_name') + .returning('first_name as deleted_first_name'), ) .with('inserted_matt', (db) => db @@ -225,14 +299,14 @@ for (const dialect of DIALECTS) { last_name: 'Damon', gender: 'male', }) - .returning('first_name as inserted_first_name') + .returning('first_name as inserted_first_name'), ) .with('updated_jennifer', (db) => db .updateTable('person') .where('first_name', '=', 'Jennifer') .set({ last_name: 'Lawrence' }) - .returning('first_name as updated_first_name') + .returning('first_name as updated_first_name'), ) .selectFrom('deleted_arnold') .innerJoin('inserted_matt', (join) => join.on(sql`1`, '=', sql`1`)) @@ -251,6 +325,7 @@ for (const dialect of DIALECTS) { 'Jennifer', ], }, + mssql: NOT_SUPPORTED, sqlite: NOT_SUPPORTED, mysql: NOT_SUPPORTED, }) diff --git a/test/typings/shared.d.ts b/test/typings/shared.d.ts index 47fcd4c77..9a7bc1afd 100644 --- a/test/typings/shared.d.ts +++ b/test/typings/shared.d.ts @@ -1,4 +1,9 @@ -import { Generated, GeneratedAlways, ColumnType } from '../../dist/cjs' +import { + ColumnType, + Generated, + GeneratedAlways, + JSONColumnType, +} from '../../dist/cjs' export interface Pet { id: Generated @@ -30,8 +35,24 @@ export interface Database { 'some_schema.movie': Movie book: Book toy: Toy + person_metadata: PersonMetadata + action: Action } +export type Action = + | { + id: GeneratedAlways + type: 'CALL_WEBHOOK' + queue_id: null + callback_url: string + } + | { + id: GeneratedAlways + type: 'DELETE_FROM_QUEUE' + queue_id: string + callback_url: null + } + export interface Person { id: Generated first_name: string @@ -43,4 +64,28 @@ export interface Person { // we never want the user to be able to insert or // update. modified_at: ColumnType + // A column that cannot be inserted, but can be updated. + deleted_at: ColumnType +} + +export interface PersonMetadata { + id: Generated + person_id: number + website: JSONColumnType<{ url: string }> + nicknames: JSONColumnType + profile: JSONColumnType<{ + auth: { + roles: string[] + last_login?: { device: string } + } + tags: string[] + }> + experience: JSONColumnType< + { + establishment: string + }[] + > + schedule: JSONColumnType<{ name: string; time: string }[][][]> + record: JSONColumnType> + array: JSONColumnType> } diff --git a/test/typings/test-d/aggregate-function.test-d.ts b/test/typings/test-d/aggregate-function.test-d.ts index 4d561190b..7ca7c51fa 100644 --- a/test/typings/test-d/aggregate-function.test-d.ts +++ b/test/typings/test-d/aggregate-function.test-d.ts @@ -1,62 +1,79 @@ -import { expectError, expectAssignable, expectNotAssignable } from 'tsd' -import { Kysely, sql } from '..' +import { + expectError, + expectAssignable, + expectNotAssignable, + expectType, +} from 'tsd' +import { Generated, Kysely, sql } from '..' import { Database } from '../shared' async function testSelectWithoutAs(db: Kysely) { const { avg, count, countAll, max, min, sum } = db.fn expectError( - db.selectFrom('person').select(avg('age')).executeTakeFirstOrThrow() + db.selectFrom('person').select(avg('age')).executeTakeFirstOrThrow(), ) expectError( - db.selectFrom('person').select(avg('age')).executeTakeFirstOrThrow() + db + .selectFrom('person') + .select(avg('age')) + .executeTakeFirstOrThrow(), ) expectError( - db.selectFrom('person').select(count('age')).executeTakeFirstOrThrow() + db.selectFrom('person').select(count('age')).executeTakeFirstOrThrow(), ) expectError( db .selectFrom('person') .select(count('age')) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( - db.selectFrom('person').select(countAll()).executeTakeFirstOrThrow() + db.selectFrom('person').select(countAll()).executeTakeFirstOrThrow(), ) expectError( - db.selectFrom('person').select(countAll()).executeTakeFirstOrThrow() + db + .selectFrom('person') + .select(countAll()) + .executeTakeFirstOrThrow(), ) expectError( - db.selectFrom('person').select(countAll('person')).executeTakeFirstOrThrow() + db + .selectFrom('person') + .select(countAll('person')) + .executeTakeFirstOrThrow(), ) expectError( db .selectFrom('person') .select(countAll('person')) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( - db.selectFrom('person').select(max('age')).executeTakeFirstOrThrow() + db.selectFrom('person').select(max('age')).executeTakeFirstOrThrow(), ) expectError( - db.selectFrom('person').select(min('age')).executeTakeFirstOrThrow() + db.selectFrom('person').select(min('age')).executeTakeFirstOrThrow(), ) expectError( - db.selectFrom('person').select(sum('age')).executeTakeFirstOrThrow() + db.selectFrom('person').select(sum('age')).executeTakeFirstOrThrow(), ) expectError( - db.selectFrom('person').select(sum('age')).executeTakeFirstOrThrow() + db + .selectFrom('person') + .select(sum('age')) + .executeTakeFirstOrThrow(), ) } @@ -90,8 +107,93 @@ async function testSelectWithDefaultGenerics(db: Kysely) { expectNotAssignable(result.total_age) } +async function testSelectExpressionBuilderWithDefaultGenerics( + db: Kysely, +) { + const result = await db + .selectFrom('person') + .select((eb) => [ + eb.fn.avg('age').as('avg_age'), + eb.fn.count('age').as('total_people'), + eb.fn.countAll().as('total_all'), + eb.fn.countAll('person').as('total_all_people'), + eb.fn.max('age').as('max_age'), + eb.fn.min('age').as('min_age'), + eb.fn.sum('age').as('total_age'), + ]) + .executeTakeFirstOrThrow() + + expectAssignable(result.avg_age) + expectNotAssignable(result.avg_age) + expectAssignable(result.total_people) + expectNotAssignable(result.total_people) + expectAssignable(result.total_all) + expectNotAssignable(result.total_all) + expectAssignable(result.total_all_people) + expectNotAssignable(result.total_all_people) + expectAssignable(result.max_age) + expectNotAssignable(result.max_age) + expectAssignable(result.min_age) + expectNotAssignable(result.min_age) + expectAssignable(result.total_age) + expectNotAssignable(result.total_age) +} + +async function testSelectExpressionBuilderWithCustomGenerics( + db: Kysely, +) { + const result = await db + .selectFrom('person') + .select((eb) => [ + eb.fn.avg('age').as('avg_age'), + eb.fn.count('age').as('total_people'), + eb.fn.countAll().as('total_all'), + eb.fn.countAll('person').as('total_all_people'), + eb.fn.max('age').as('max_age'), + eb.fn.min('age').as('min_age'), + eb.fn.sum('age').as('total_age'), + eb.fn.agg('max', ['age']).as('another_max_age'), + ]) + .executeTakeFirstOrThrow() + + expectType(result.avg_age) + expectType(result.total_people) + expectType(result.total_all) + expectType(result.total_all_people) + expectType(result.max_age) + expectType(result.min_age) + expectType(result.total_age) + expectType(result.another_max_age) +} + +async function testSelectExpressionBuilderWithSubExpressions( + db: Kysely, +) { + const result = await db + .selectFrom('person') + .select((eb) => [ + eb.fn.avg(eb.ref('age')).as('avg_age'), + eb.fn.count(eb.ref('age')).as('total_people'), + eb.fn.countAll().as('total_all'), + eb.fn.countAll('person').as('total_all_people'), + eb.fn.max(eb.ref('age').$castTo()).as('max_age'), + eb.fn.min(eb.ref('age')).as('min_age'), + eb.fn.sum(eb.ref('age')).as('total_age'), + ]) + + .executeTakeFirstOrThrow() + + expectType(result.avg_age) + expectType(result.total_people) + expectType(result.total_all) + expectType(result.total_all_people) + expectType(result.max_age) + expectType(result.min_age) + expectType(result.total_age) +} + async function testSelectWithCustomGenerics(db: Kysely) { - const { avg, count, countAll, max, min, sum } = db.fn + const { avg, count, countAll, max, min, sum, agg } = db.fn const result = await db .selectFrom('person') @@ -100,10 +202,11 @@ async function testSelectWithCustomGenerics(db: Kysely) { .select(count('age').as('total_people')) .select(countAll().as('total_all')) .select(countAll('person').as('total_all_people')) - .select(max('age').as('nullable_max_age')) - .select(min('age').as('nullable_min_age')) + .select(max('age').as('nullable_max_age')) + .select(min('age').as('nullable_min_age')) .select(sum('age').as('total_age')) .select(sum('age').as('nullable_total_age')) + .select(agg('max', ['age']).as('max_age')) .executeTakeFirstOrThrow() expectAssignable(result.avg_age) @@ -124,56 +227,7 @@ async function testSelectWithCustomGenerics(db: Kysely) { expectNotAssignable(result.total_age) expectAssignable(result.nullable_total_age) expectNotAssignable(result.nullable_total_age) - - expectError( - db - .selectFrom('person') - .select(max('age').as('max_lie_return_type')) - .executeTakeFirstOrThrow() - ) - - expectError( - db - .selectFrom('person') - .select(max('age').as('another_max_lie_return_type')) - .executeTakeFirstOrThrow() - ) - - expectError( - db - .selectFrom('person') - .select( - max('age').as( - 'max_explicit_return_type_but_no_string_ref' - ) - ) - .executeTakeFirstOrThrow() - ) - - expectError( - db - .selectFrom('person') - .select(min('age').as('min_lie_return_type')) - .executeTakeFirstOrThrow() - ) - - expectError( - db - .selectFrom('person') - .select(min('age').as('another_min_lie_return_type')) - .executeTakeFirstOrThrow() - ) - - expectError( - db - .selectFrom('person') - .select( - min('age').as( - 'min_explicit_return_type_but_no_string_ref' - ) - ) - .executeTakeFirstOrThrow() - ) + expectType(result.max_age) } async function testSelectUnexpectedColumn(db: Kysely) { @@ -183,70 +237,70 @@ async function testSelectUnexpectedColumn(db: Kysely) { db .selectFrom('person') .select(avg('no_such_column').as('avg_age')) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( db .selectFrom('person') .select(avg('no_such_column').as('avg_age')) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( db .selectFrom('person') .select(count('no_such_column').as('total_people')) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( db .selectFrom('person') .select(count('no_such_column').as('total_people')) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( db .selectFrom('person') .select(countAll('no_such_table').as('total_all_people')) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( db .selectFrom('person') .select(countAll('no_such_table').as('total_all_people')) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( db .selectFrom('person') .select(max('no_such_column').as('max_age')) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( db .selectFrom('person') .select(min('no_such_column').as('min_age')) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( db .selectFrom('person') .select(sum('no_such_column').as('total_age')) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( db .selectFrom('person') .select(sum('no_such_column').as('total_age')) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) } @@ -337,58 +391,58 @@ async function testWithFilterWhere(db: Kysely) { // Table and column db.selectFrom('person').select( - avg('age').filterWhere('person.gender', '=', 'female').as('avg_age') + avg('age').filterWhere('person.gender', '=', 'female').as('avg_age'), ) // Schema, table and column db.selectFrom('some_schema.movie').select( - avg('stars').filterWhere('some_schema.movie.stars', '>', 0).as('avg_stars') + avg('stars').filterWhere('some_schema.movie.stars', '>', 0).as('avg_stars'), ) // Subquery in LHS db.selectFrom('person').select( avg('age') .filterWhere((qb) => qb.selectFrom('movie').select('stars'), '>', 0) - .as('avg_age') + .as('avg_age'), ) // Subquery in RHS db.selectFrom('movie').select( avg('stars') - .filterWhere(sql`${'female'}`, '=', (qb) => - qb.selectFrom('person').select('gender') + .filterWhere(sql`${'female'}`, '=', (qb) => + qb.selectFrom('person').select('gender'), ) - .as('avg_stars') + .as('avg_stars'), ) // Raw expression db.selectFrom('person').select( avg('age') - .filterWhere('first_name', '=', sql`'foo'`) + .filterWhere('first_name', '=', sql`'foo'`) .filterWhere('first_name', '=', sql`'foo'`) .filterWhere(sql`whatever`, '=', 1) .filterWhere(sql`whatever`, '=', true) .filterWhere(sql`whatever`, '=', '1') - .as('avg_age') + .as('avg_age'), ) // List value db.selectFrom('person').select( - avg('age').filterWhere('gender', 'in', ['female', 'male']).as('avg_age') + avg('age').filterWhere('gender', 'in', ['female', 'male']).as('avg_age'), ) // Raw operator db.selectFrom('person').select( avg('age') .filterWhere('person.age', sql`lol`, 25) - .as('avg_age') + .as('avg_age'), ) // Invalid operator expectError( db .selectFrom('person') - .select(avg('age').filterWhere('person.age', 'lol', 25).as('avg_age')) + .select(avg('age').filterWhere('person.age', 'lol', 25).as('avg_age')), ) // Invalid table @@ -396,8 +450,8 @@ async function testWithFilterWhere(db: Kysely) { db .selectFrom('person') .select((eb) => - eb.fn.avg('age').filterWhere('movie.stars', '=', 25).as('avg_age') - ) + eb.fn.avg('age').filterWhere('movie.stars', '=', 25).as('avg_age'), + ), ) // Invalid column @@ -405,15 +459,15 @@ async function testWithFilterWhere(db: Kysely) { db .selectFrom('person') .select((eb) => - eb.fn.avg('age').filterWhere('stars', '=', 25).as('avg_age') - ) + eb.fn.avg('age').filterWhere('stars', '=', 25).as('avg_age'), + ), ) // Invalid type for column expectError( db .selectFrom('person') - .select(avg('age').filterWhere('first_name', '=', 25).as('avg_age')) + .select(avg('age').filterWhere('first_name', '=', 25).as('avg_age')), ) // Invalid type for column @@ -421,8 +475,8 @@ async function testWithFilterWhere(db: Kysely) { db .selectFrom('person') .select( - avg('age').filterWhere('gender', '=', 'not_a_gender').as('avg_age') - ) + avg('age').filterWhere('gender', '=', 'not_a_gender').as('avg_age'), + ), ) // Invalid type for column @@ -432,8 +486,8 @@ async function testWithFilterWhere(db: Kysely) { .select( avg('age') .filterWhere('gender', 'in', ['female', 'not_a_gender']) - .as('avg_age') - ) + .as('avg_age'), + ), ) // Invalid type for column @@ -441,8 +495,10 @@ async function testWithFilterWhere(db: Kysely) { db .selectFrom('some_schema.movie') .select( - avg('stars').filterWhere('some_schema.movie.id', '=', 1).as('avg_stars') - ) + avg('stars') + .filterWhere('some_schema.movie.id', '=', 1) + .as('avg_stars'), + ), ) // Invalid type for column @@ -452,10 +508,10 @@ async function testWithFilterWhere(db: Kysely) { .filterWhere( (qb) => qb.selectFrom('person').select('gender'), '=', - 'not_a_gender' + 'not_a_gender', ) - .as('avg_stars') - ) + .as('avg_stars'), + ), ) // Invalid type for column @@ -463,8 +519,8 @@ async function testWithFilterWhere(db: Kysely) { db.selectFrom('person').select( avg('age') .filterWhere('first_name', '=', sql`1`) - .as('avg_age') - ) + .as('avg_age'), + ), ) // Invalid type for column @@ -472,8 +528,8 @@ async function testWithFilterWhere(db: Kysely) { db.selectFrom('person').select( avg('age') .filterWhere(sql`first_name`, '=', 1) - .as('avg_age') - ) + .as('avg_age'), + ), ) } @@ -483,19 +539,19 @@ async function testWithFilterWhereRef(db: Kysely) { // Column name db.selectFrom('person') .select( - avg('age').filterWhereRef('first_name', '=', 'last_name').as('avg_age') + avg('age').filterWhereRef('first_name', '=', 'last_name').as('avg_age'), ) .select( - count('id').filterWhereRef('first_name', '=', 'last_name').as('count') + count('id').filterWhereRef('first_name', '=', 'last_name').as('count'), ) .select( - max('age').filterWhereRef('first_name', '=', 'last_name').as('max_age') + max('age').filterWhereRef('first_name', '=', 'last_name').as('max_age'), ) .select( - min('age').filterWhereRef('first_name', '=', 'last_name').as('min_age') + min('age').filterWhereRef('first_name', '=', 'last_name').as('min_age'), ) .select( - sum('age').filterWhereRef('first_name', '=', 'last_name').as('total_age') + sum('age').filterWhereRef('first_name', '=', 'last_name').as('total_age'), ) // Table and column @@ -503,17 +559,17 @@ async function testWithFilterWhereRef(db: Kysely) { .select( avg('age') .filterWhereRef('person.first_name', '=', 'last_name') - .as('avg_age') + .as('avg_age'), ) .select( count('id') .filterWhereRef('first_name', '=', 'person.last_name') - .as('count') + .as('count'), ) .select( max('age') .filterWhereRef('person.first_name', '=', 'person.last_name') - .as('max_age') + .as('max_age'), ) // Schema, table and column @@ -521,27 +577,27 @@ async function testWithFilterWhereRef(db: Kysely) { .select( avg('stars') .filterWhereRef('some_schema.movie.id', '=', 'stars') - .as('avg_stars') + .as('avg_stars'), ) .select( count('id') .filterWhereRef('some_schema.movie.id', '=', 'movie.stars') - .as('count') + .as('count'), ) .select( max('stars') .filterWhereRef('some_schema.movie.id', '=', 'some_schema.movie.stars') - .as('max_stars') + .as('max_stars'), ) .select( min('stars') .filterWhereRef('movie.id', '=', 'some_schema.movie.stars') - .as('min_stars') + .as('min_stars'), ) .select( sum('stars') .filterWhereRef('id', '=', 'some_schema.movie.stars') - .as('total_stars') + .as('total_stars'), ) // Subquery in LHS @@ -550,25 +606,25 @@ async function testWithFilterWhereRef(db: Kysely) { .filterWhereRef( (qb) => qb.selectFrom('movie').select('stars'), '>', - 'age' + 'age', ) - .as('avg_age') + .as('avg_age'), ) // Subquery in RHS db.selectFrom('person').select( avg('age') .filterWhereRef('age', '>', (qb) => - qb.selectFrom('movie').select('stars') + qb.selectFrom('movie').select('stars'), ) - .as('avg_age') + .as('avg_age'), ) // Raw operator db.selectFrom('person').select( avg('age') .filterWhereRef('first_name', sql`lol`, 'last_name') - .as('avg_age') + .as('avg_age'), ) // Invalid operator @@ -578,8 +634,8 @@ async function testWithFilterWhereRef(db: Kysely) { .select( avg('age') .filterWhereRef('first_name', 'lol', 'last_name') - .as('avg_age') - ) + .as('avg_age'), + ), ) // Invalid table LHS @@ -587,8 +643,11 @@ async function testWithFilterWhereRef(db: Kysely) { db .selectFrom('person') .select((eb) => - eb.fn.avg('age').filterWhereRef('movie.stars', '>', 'age').as('avg_age') - ) + eb.fn + .avg('age') + .filterWhereRef('movie.stars', '>', 'age') + .as('avg_age'), + ), ) // Invalid table RHS @@ -596,8 +655,11 @@ async function testWithFilterWhereRef(db: Kysely) { db .selectFrom('person') .select((eb) => - eb.fn.avg('age').filterWhereRef('age', '>', 'movie.stars').as('avg_age') - ) + eb.fn + .avg('age') + .filterWhereRef('age', '>', 'movie.stars') + .as('avg_age'), + ), ) // Invalid column LHS @@ -605,8 +667,8 @@ async function testWithFilterWhereRef(db: Kysely) { db .selectFrom('person') .select((eb) => - eb.fn.avg('age').filterWhereRef('stars', '>', 'age').as('avg_age') - ) + eb.fn.avg('age').filterWhereRef('stars', '>', 'age').as('avg_age'), + ), ) // Invalid column RHS @@ -614,8 +676,8 @@ async function testWithFilterWhereRef(db: Kysely) { db .selectFrom('person') .select((eb) => - eb.fn.avg('age').filterWhereRef('age', '>', 'stars').as('avg_age') - ) + eb.fn.avg('age').filterWhereRef('age', '>', 'stars').as('avg_age'), + ), ) } @@ -646,27 +708,27 @@ async function testSelectWithOverAndPartitionBySingle(db: Kysely) { .select( avg('age') .over((ob) => ob.partitionBy('gender')) - .as('avg_age') + .as('avg_age'), ) .select( count('age') .over((ob) => ob.partitionBy('gender')) - .as('total_people') + .as('total_people'), ) .select( max('age') .over((ob) => ob.partitionBy('gender')) - .as('max_age') + .as('max_age'), ) .select( min('age') .over((ob) => ob.partitionBy('gender')) - .as('min_age') + .as('min_age'), ) .select( sum('age') .over((ob) => ob.partitionBy('gender')) - .as('total_age') + .as('total_age'), ) .executeTakeFirstOrThrow() @@ -685,35 +747,35 @@ async function testSelectWithOverAndPartitionByMultiple(db: Kysely) { .select( avg('age') .over((ob) => ob.partitionBy(['gender'])) - .as('avg_age') + .as('avg_age'), ) .select( count('age') .over((ob) => - ob.partitionBy(['gender']).partitionBy('person.first_name') + ob.partitionBy(['gender']).partitionBy('person.first_name'), ) - .as('total_people') + .as('total_people'), ) .select( max('age') .over((ob) => - ob.partitionBy(['gender']).partitionBy('person.first_name') + ob.partitionBy(['gender']).partitionBy('person.first_name'), ) - .as('max_age') + .as('max_age'), ) .select( min('age') .over((ob) => - ob.partitionBy(['gender']).partitionBy('person.first_name') + ob.partitionBy(['gender']).partitionBy('person.first_name'), ) - .as('min_age') + .as('min_age'), ) .select( sum('age') .over((ob) => - ob.partitionBy(['gender']).partitionBy('person.first_name') + ob.partitionBy(['gender']).partitionBy('person.first_name'), ) - .as('total_age') + .as('total_age'), ) .executeTakeFirstOrThrow() @@ -725,7 +787,7 @@ async function testSelectWithOverAndPartitionByMultiple(db: Kysely) { } async function testSelectWithOverAndPartitionByUnexpectedColumns( - db: Kysely + db: Kysely, ) { const { avg, count, max, min, sum } = db.fn @@ -735,9 +797,9 @@ async function testSelectWithOverAndPartitionByUnexpectedColumns( .select( avg('age') .over((ob) => ob.partitionBy('no_such_column')) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) expectError( db @@ -745,9 +807,9 @@ async function testSelectWithOverAndPartitionByUnexpectedColumns( .select( avg('age') .over((ob) => ob.partitionBy(['no_such_column'])) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) expectError( db @@ -755,9 +817,9 @@ async function testSelectWithOverAndPartitionByUnexpectedColumns( .select( count('age') .over((ob) => ob.partitionBy('no_such_column')) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) expectError( db @@ -765,9 +827,9 @@ async function testSelectWithOverAndPartitionByUnexpectedColumns( .select( count('age') .over((ob) => ob.partitionBy(['no_such_column'])) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) expectError( db @@ -775,9 +837,9 @@ async function testSelectWithOverAndPartitionByUnexpectedColumns( .select( max('age') .over((ob) => ob.partitionBy('no_such_column')) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) expectError( db @@ -785,9 +847,9 @@ async function testSelectWithOverAndPartitionByUnexpectedColumns( .select( max('age') .over((ob) => ob.partitionBy(['no_such_column'])) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) expectError( db @@ -795,9 +857,9 @@ async function testSelectWithOverAndPartitionByUnexpectedColumns( .select( min('age') .over((ob) => ob.partitionBy('no_such_column')) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) expectError( db @@ -805,9 +867,9 @@ async function testSelectWithOverAndPartitionByUnexpectedColumns( .select( min('age') .over((ob) => ob.partitionBy(['no_such_column'])) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) expectError( db @@ -815,9 +877,9 @@ async function testSelectWithOverAndPartitionByUnexpectedColumns( .select( sum('age') .over((ob) => ob.partitionBy('no_such_column')) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) expectError( db @@ -825,9 +887,9 @@ async function testSelectWithOverAndPartitionByUnexpectedColumns( .select( sum('age') .over((ob) => ob.partitionBy(['no_such_column'])) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) } @@ -839,27 +901,27 @@ async function testSelectWithOverAndOrderBySingle(db: Kysely) { .select( avg('age') .over((ob) => ob.orderBy('gender')) - .as('avg_age') + .as('avg_age'), ) .select( count('age') .over((ob) => ob.orderBy('gender')) - .as('total_people') + .as('total_people'), ) .select( max('age') .over((ob) => ob.orderBy('gender')) - .as('max_age') + .as('max_age'), ) .select( min('age') .over((ob) => ob.orderBy('gender')) - .as('min_age') + .as('min_age'), ) .select( sum('age') .over((ob) => ob.orderBy('gender')) - .as('total_age') + .as('total_age'), ) .executeTakeFirstOrThrow() @@ -878,27 +940,27 @@ async function testSelectWithOverAndOrderByMultiple(db: Kysely) { .select( avg('age') .over((ob) => ob.orderBy('gender').orderBy('first_name', 'desc')) - .as('avg_age') + .as('avg_age'), ) .select( count('age') .over((ob) => ob.orderBy('gender').orderBy('first_name', 'desc')) - .as('total_people') + .as('total_people'), ) .select( max('age') .over((ob) => ob.orderBy('gender').orderBy('first_name', 'desc')) - .as('max_age') + .as('max_age'), ) .select( min('age') .over((ob) => ob.orderBy('gender').orderBy('first_name', 'desc')) - .as('min_age') + .as('min_age'), ) .select( sum('age') .over((ob) => ob.orderBy('gender').orderBy('first_name', 'desc')) - .as('total_age') + .as('total_age'), ) .executeTakeFirstOrThrow() @@ -910,7 +972,7 @@ async function testSelectWithOverAndOrderByMultiple(db: Kysely) { } async function testSelectWithOverAndOrderByUnexpectedColumns( - db: Kysely + db: Kysely, ) { const { avg, count, max, min, sum } = db.fn @@ -920,9 +982,9 @@ async function testSelectWithOverAndOrderByUnexpectedColumns( .select( avg('age') .over((ob) => ob.orderBy('no_such_column')) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) expectError( db @@ -930,9 +992,9 @@ async function testSelectWithOverAndOrderByUnexpectedColumns( .select( count('age') .over((ob) => ob.orderBy('no_such_column')) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) expectError( db @@ -940,9 +1002,9 @@ async function testSelectWithOverAndOrderByUnexpectedColumns( .select( max('age') .over((ob) => ob.orderBy('no_such_column')) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) expectError( db @@ -950,9 +1012,9 @@ async function testSelectWithOverAndOrderByUnexpectedColumns( .select( min('age') .over((ob) => ob.orderBy('no_such_column')) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) expectError( db @@ -960,9 +1022,9 @@ async function testSelectWithOverAndOrderByUnexpectedColumns( .select( sum('age') .over((ob) => ob.orderBy('no_such_column')) - .as('avg_age') + .as('avg_age'), ) - .executeTakeFirst() + .executeTakeFirst(), ) } @@ -985,7 +1047,7 @@ async function testSelectAsCustomFunctionArgument(db: Kysely) { .select(({ fn }) => [ fn('round', [fn.avg('NO_SUCH_COLUMN')]).as('avg_age'), ]) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( @@ -994,7 +1056,7 @@ async function testSelectAsCustomFunctionArgument(db: Kysely) { .select(({ fn }) => [ fn('round', [fn.count('NO_SUCH_COLUMN')]).as('avg_age'), ]) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( @@ -1003,7 +1065,7 @@ async function testSelectAsCustomFunctionArgument(db: Kysely) { .select(({ fn }) => [ fn('round', [fn.max('NO_SUCH_COLUMN')]).as('avg_age'), ]) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( @@ -1012,7 +1074,7 @@ async function testSelectAsCustomFunctionArgument(db: Kysely) { .select(({ fn }) => [ fn('round', [fn.min('NO_SUCH_COLUMN')]).as('avg_age'), ]) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) expectError( @@ -1021,6 +1083,78 @@ async function testSelectAsCustomFunctionArgument(db: Kysely) { .select(({ fn }) => [ fn('round', [fn.sum('NO_SUCH_COLUMN')]).as('avg_age'), ]) - .executeTakeFirstOrThrow() + .executeTakeFirstOrThrow(), ) } + +interface DB764 { + order: Order764 + orderDetails: OrderDetails764 +} + +interface OrderDetails764 { + id: Generated + orderId: string + itemName: string + itemType: string + quantity: number + unlimited: true +} + +interface Order764 { + id: Generated +} + +enum ItemType764 { + FOOD = 'FOOD', + FEELING = 'FEELING', +} + +// https://github.com/kysely-org/kysely/issues/764 +async function testIssue764(db: Kysely) { + await db + .with('OrderAggregates', (db) => + db + .selectFrom('orderDetails') + .innerJoin('order', 'order.id', 'orderDetails.orderId') + .select([ + 'orderDetails.itemName', + 'orderDetails.itemType', + 'order.id as order_id', + (eb) => eb.fn.max('orderDetails.quantity').as('MaxQuantity'), + (eb) => eb.fn.sum('orderDetails.quantity').as('SumQuantity'), + (eb) => + eb + .fn('bool_or', [eb.ref('orderDetails.unlimited')]) + .as('AnyUnlimited'), + ]) + .groupBy(['order_id']), + ) + .selectFrom('OrderAggregates') + .select(['order_id', 'OrderAggregates.itemName']) + .select((eb) => + eb + .case() + .when('OrderAggregates.itemType', '=', ItemType764.FOOD) + .then( + eb + .case() + .when(sql`bool_or(${eb.ref('AnyUnlimited')})`) + .then(-1) + .else(eb.fn.max('SumQuantity')) + .end(), + ) + .when('OrderAggregates.itemType', '=', ItemType764.FEELING) + .then(eb.fn.max('MaxQuantity')) + .else(0) + .end() + .as('totalQuantity'), + ) + .groupBy([ + 'OrderAggregates.itemName', + 'OrderAggregates.AnyUnlimited', + 'OrderAggregates.MaxQuantity', + 'OrderAggregates.SumQuantity', + ]) + .execute() +} diff --git a/test/typings/test-d/alter-table.test-d.ts b/test/typings/test-d/alter-table.test-d.ts new file mode 100644 index 000000000..2519baa7f --- /dev/null +++ b/test/typings/test-d/alter-table.test-d.ts @@ -0,0 +1,38 @@ +import { expectError, expectType } from 'tsd' +import { AlterTableBuilder, Kysely } from '..' +import { Database } from '../shared' +import { AlterTableExecutor } from '../../../dist/cjs/schema/alter-table-executor' + +async function testAlterTableWithAddUniqueConstraint(db: Kysely) { + expectType(db.schema.alterTable('test')) + + expectType( + db.schema.alterTable('test').addUniqueConstraint('a_unique', ['a']), + ) + + expectType( + db.schema + .alterTable('test') + .addUniqueConstraint('a_unique', ['a'], (uc) => uc.nullsNotDistinct()), + ) + + expectError( + db.schema.alterTable('test').addUniqueConstraint('a_unique', null), + ) + expectError(db.schema.alterTable('test').addUniqueConstraint('a_unique', [1])) + expectError( + db.schema + .alterTable('test') + .addUniqueConstraint(null, ['a'], (uc) => uc.nullsNotDistinct()), + ) + expectError( + db.schema + .alterTable('test') + .addUniqueConstraint('a_unique', [1], (uc) => uc.nullsNotDistinct()), + ) + expectError( + db.schema + .alterTable('test') + .addUniqueConstraint('a_unique', ['a'], 'wrong option'), + ) +} diff --git a/test/typings/test-d/assert-type.test-d.ts b/test/typings/test-d/assert-type.test-d.ts index 8a2ca4409..f5fac669d 100644 --- a/test/typings/test-d/assert-type.test-d.ts +++ b/test/typings/test-d/assert-type.test-d.ts @@ -41,7 +41,7 @@ async function testAssertType(db: Kysely) { .selectFrom('person') .select('first_name as fn') .$assertType<{ wrong: string }>() - .execute() + .execute(), ) expectError( @@ -49,6 +49,6 @@ async function testAssertType(db: Kysely) { .selectFrom('person') .select('first_name as fn') .$assertType<{ fn: string; extra: number }>() - .execute() + .execute(), ) } diff --git a/test/typings/test-d/case.test-d.ts b/test/typings/test-d/case.test-d.ts index ab7ae5a7b..772fb8a5d 100644 --- a/test/typings/test-d/case.test-d.ts +++ b/test/typings/test-d/case.test-d.ts @@ -4,29 +4,29 @@ import { Database } from '../shared' async function testCase(eb: ExpressionBuilder) { // case...when...then...when...then...end - expectType>( + expectType>( eb .case() .when('gender', '=', 'male') .then('Mr.') .when('gender', '=', 'female') .then(12) - .end() + .end(), ) // case...when...then...when...then...end (as const) - expectType>( + expectType>( eb .case() .when('gender', '=', 'male') .then('Mr.' as const) .when('gender', '=', 'female') .then(12 as const) - .end() + .end(), ) // case...when...then...when...then...else...end - expectType>( + expectType>( eb .case() .when('gender', '=', 'male') @@ -34,11 +34,11 @@ async function testCase(eb: ExpressionBuilder) { .when('gender', '=', 'female') .then(12) .else(true) - .end() + .end(), ) // case...when...then...when...then...else...end (as const) - expectType>( + expectType>( eb .case() .when('gender', '=', 'male') @@ -46,11 +46,13 @@ async function testCase(eb: ExpressionBuilder) { .when('gender', '=', 'female') .then(12 as const) .else(true as const) - .end() + .end(), ) // nested case - expectType>( + expectType< + ExpressionWrapper + >( eb .case() .when('gender', '=', 'male') @@ -62,23 +64,23 @@ async function testCase(eb: ExpressionBuilder) { .when('marital_status', '=', 'single') .then('Ms.' as const) .else('Mrs.' as const) - .end() + .end(), ) - .end() + .end(), ) // references - expectType>( + expectType>( eb .case() .when('gender', '=', 'male') .then(eb.ref('first_name')) .else(eb.ref('age')) - .end() + .end(), ) // expressions - expectType>( + expectType>( eb .case() .when('gender', '=', 'male') @@ -87,9 +89,18 @@ async function testCase(eb: ExpressionBuilder) { eb.val('Mr.'), sql.lit(' '), eb.ref('last_name'), - ]) + ]), ) - .end() + .end(), + ) + + // subquery + expectType>( + eb + .case() + .when('gender', '=', 'male') + .then(eb.selectFrom('person').select('first_name')) + .end(), ) // errors @@ -102,12 +113,12 @@ async function testCase(eb: ExpressionBuilder) { function testCaseValue(eb: ExpressionBuilder) { // case...value...when...then...when...then...end - expectType>( - eb.case('gender').when('male').then('Mr.').when('female').then(12).end() + expectType>( + eb.case('gender').when('male').then('Mr.').when('female').then(12).end(), ) // case...value...when...then...when...then...else...end - expectType>( + expectType>( eb .case('gender') .when('male') @@ -115,11 +126,13 @@ function testCaseValue(eb: ExpressionBuilder) { .when('female') .then(12) .else(true) - .end() + .end(), ) // nested case - expectType>( + expectType< + ExpressionWrapper + >( eb .case('gender') .when('male') @@ -131,9 +144,9 @@ function testCaseValue(eb: ExpressionBuilder) { .when('single') .then('Ms.' as const) .else('Mrs.' as const) - .end() + .end(), ) - .end() + .end(), ) // errors diff --git a/test/typings/test-d/clear.test-d.ts b/test/typings/test-d/clear.test-d.ts index 956627b6b..e823a4501 100644 --- a/test/typings/test-d/clear.test-d.ts +++ b/test/typings/test-d/clear.test-d.ts @@ -21,3 +21,81 @@ async function testClearSelect(db: Kysely) { expectType<{ age: number }>(r2) } + +async function testClearInsert(db: Kysely) { + const r1 = await db + .insertInto('person') + .values({ + first_name: 'Bruce', + last_name: 'Willis', + age: 68, + gender: 'male', + }) + .returning(['first_name', 'gender']) + .clearReturning() + .returning('id') + .executeTakeFirstOrThrow() + + expectType<{ id: number }>(r1) + + const r2 = await db + .insertInto('person') + .values({ + first_name: 'Bruce', + last_name: 'Willis', + age: 68, + gender: 'male', + }) + .returningAll() + .clearReturning() + .returning('age') + .executeTakeFirstOrThrow() + + expectType<{ age: number }>(r2) +} + +async function testClearUpdate(db: Kysely) { + const r1 = await db + .updateTable('person') + .set({ age: 76 }) + .where('first_name', '=', 'Arnold') + .returning(['first_name', 'gender']) + .clearReturning() + .returning('id') + .executeTakeFirstOrThrow() + + expectType<{ id: number }>(r1) + + const r2 = await db + .updateTable('person') + .set({ age: 76 }) + .where('first_name', '=', 'Arnold') + .returningAll() + .clearReturning() + .returning('age') + .executeTakeFirstOrThrow() + + expectType<{ age: number }>(r2) +} + +async function testClearDelete(db: Kysely) { + const r1 = await db + .deleteFrom('person') + .where('first_name', '=', 'Bruce') + .returning(['first_name', 'gender']) + .clearReturning() + .returning('id') + .executeTakeFirstOrThrow() + + expectType<{ id: number }>(r1) + + const r2 = await db + .deleteFrom('person') + .where('first_name', '=', 'Bruce') + .returningAll() + .clearReturning() + .returning('age') + .executeTakeFirstOrThrow() + + expectType<{ age: number }>(r2) +} diff --git a/test/typings/test-d/coalesce.test-d.ts b/test/typings/test-d/coalesce.test-d.ts index f546a6b6e..f7d0e6630 100644 --- a/test/typings/test-d/coalesce.test-d.ts +++ b/test/typings/test-d/coalesce.test-d.ts @@ -55,7 +55,7 @@ async function testCoalesceSingle(db: Kysely) { expectType<{ void: null }>(r7) expectError( - db.selectFrom('person').select(coalesce('no_such_column').as('alias')) + db.selectFrom('person').select(coalesce('no_such_column').as('alias')), ) // no alias @@ -84,8 +84,8 @@ async function testCoalesceMultiple(db: Kysely) { .selectFrom('person') .select( coalesce(value(null), 'last_name', db.fn.max('first_name'), 'age').as( - 'field' - ) + 'field', + ), ) .groupBy(['last_name', 'first_name', 'age']) .execute() @@ -96,9 +96,9 @@ async function testCoalesceMultiple(db: Kysely) { .selectFrom('person') .select( coalesce( - db.fn.max('first_name'), - sql`${sql.lit('N/A')}` - ).as('max_first_name') + db.fn.max('first_name'), + sql`${sql.lit('N/A')}`, + ).as('max_first_name'), ) .execute() expectType<{ max_first_name: string }>(r3) diff --git a/test/typings/test-d/create-table.test-d.ts b/test/typings/test-d/create-table.test-d.ts new file mode 100644 index 000000000..de7cf7ac1 --- /dev/null +++ b/test/typings/test-d/create-table.test-d.ts @@ -0,0 +1,88 @@ +import { expectError, expectType } from 'tsd' +import { CreateTableBuilder, Kysely } from '..' +import { Database } from '../shared' + +async function testCreateTableWithSeveralColumns(db: Kysely) { + expectType>(db.schema.createTable('person')) + + expectType>( + db.schema.createTable('person').addColumn('a', 'varchar(255)'), + ) + + expectError( + db.schema + .createTable(1) + .addColumn('a', 'varchar(255)') + .addColumn('b', 'varchar(255)'), + ) + expectError( + db.schema + .createTable('test') + .addColumn(null, 'varchar(255)') + .addColumn('b', 'varchar(255)'), + ) + expectError( + db.schema + .createTable('test') + .addColumn('a', 'varchar(255)') + .addColumn('b', 'test_type'), + ) +} + +async function testCreateTableWithAddUniqueConstraint(db: Kysely) { + expectType>( + db.schema + .createTable('person') + .addColumn('a', 'varchar(255)') + .addUniqueConstraint('a_unique', ['a']), + ) + + expectType>( + db.schema + .createTable('person') + .addColumn('a', 'varchar(255)') + .addUniqueConstraint('a_unique', ['a'], (uc) => uc.nullsNotDistinct()), + ) + + expectError( + db.schema + .createTable('test') + .addColumn('a', 'varchar(255)') + .addUniqueConstraint(1, ['a']), + ) + expectError( + db.schema + .createTable('test') + .addColumn('a', 'varchar(255)') + .addUniqueConstraint('a_unique', 'test'), + ) + expectError( + db.schema + .createTable('test') + .addColumn('a', 'varchar(255)') + .addUniqueConstraint('a_unique', [1]), + ) + expectError( + db.schema + .createTable('test') + .addColumn('a', 'varchar(255)') + .addUniqueConstraint(null, ['a'], (uc) => uc.nullsNotDistinct()), + ) + expectError( + db.schema + .createTable('test') + .addColumn('a', 'varchar(255)') + .addUniqueConstraint('a_unique', [1], (uc) => uc.nullsNotDistinct()), + ) + expectError( + db.schema + .createTable('test') + .addColumn('a', 'varchar(255)') + .addUniqueConstraint('a_unique', ['a'], 'wrong option'), + ) +} + +async function testCreateTableWithAsStatement(db: Kysely) { + expectError(db.schema.createTable('test').as()) + expectError(db.schema.createTable('test').as('test')) +} diff --git a/test/typings/test-d/delete-query-builder.test-d.ts b/test/typings/test-d/delete-query-builder.test-d.ts index ce57b70d7..f827d0a3b 100644 --- a/test/typings/test-d/delete-query-builder.test-d.ts +++ b/test/typings/test-d/delete-query-builder.test-d.ts @@ -1,5 +1,5 @@ import { expectError, expectType } from 'tsd' -import { Kysely, DeleteResult, Selectable } from '..' +import { Kysely, DeleteResult, Selectable, sql } from '..' import { Database, Person, Pet } from '../shared' async function testDelete(db: Kysely) { @@ -17,7 +17,6 @@ async function testDelete(db: Kysely) { .deleteFrom('person') .using(['pet', 'toy']) .where('pet.species', '=', 'cat') - .orWhere('toy.price', '=', 0) .executeTakeFirstOrThrow() expectType(r3) @@ -26,7 +25,6 @@ async function testDelete(db: Kysely) { .using(['person', 'pet']) .innerJoin('toy', 'toy.pet_id', 'pet.id') .where('pet.species', '=', 'cat') - .orWhere('toy.price', '=', 0) .executeTakeFirstOrThrow() expectType(r4) @@ -35,7 +33,6 @@ async function testDelete(db: Kysely) { .using(['person', 'pet']) .leftJoin('toy', 'toy.pet_id', 'pet.id') .where('pet.species', '=', 'cat') - .orWhere('toy.price', '=', 0) .executeTakeFirstOrThrow() expectType(r5) @@ -62,47 +59,49 @@ async function testDelete(db: Kysely) { expectError(db.deleteFrom('pet').using('NO_SUCH_TABLE')) expectError(db.deleteFrom('pet').using(['pet', 'NO_SUCH_TABLE'])) expectError( - db.deleteFrom('pet').using('pet').innerJoin('NO_SUCH_TABLE', 'pet.id', 'b') + db.deleteFrom('pet').using('pet').innerJoin('NO_SUCH_TABLE', 'pet.id', 'b'), ) expectError( db .deleteFrom('pet') .using('pet') - .innerJoin('person', 'NO_SUCH_COLUMN', 'pet.owner_id') + .innerJoin('person', 'NO_SUCH_COLUMN', 'pet.owner_id'), ) expectError( - db.deleteFrom('pet').using('pet').leftJoin('NO_SUCH_TABLE', 'pet.id', 'b') + db.deleteFrom('pet').using('pet').leftJoin('NO_SUCH_TABLE', 'pet.id', 'b'), ) expectError( db .deleteFrom('pet') .using('pet') - .leftJoin('person', 'NO_SUCH_COLUMN', 'pet.owner_id') + .leftJoin('person', 'NO_SUCH_COLUMN', 'pet.owner_id'), ) +} - const r8 = await db +async function testReturning(db: Kysely) { + const r1 = await db .deleteFrom('person') .using(['person', 'pet']) .leftJoin('toy', 'toy.pet_id', 'pet.id') - .where('pet.species', '=', 'cat') - .orWhere('toy.price', '=', 0) + .where((eb) => + eb.or([eb('pet.species', '=', 'cat'), eb('toy.price', '=', 0)]), + ) .returningAll('person') .execute() - expectType[]>(r8) + expectType[]>(r1) - const r9 = await db + const r2 = await db .deleteFrom('pet') .where('pet.species', '=', 'cat') .returningAll('pet') .execute() - expectType[]>(r9) + expectType[]>(r2) - const r10 = await db + const r3 = await db .deleteFrom('person') .using(['person', 'pet']) .leftJoin('toy', 'toy.pet_id', 'pet.id') .where('pet.species', '=', 'cat') - .orWhere('toy.price', '=', 0) .returningAll(['pet', 'toy', 'person']) .execute() expectType< @@ -114,6 +113,7 @@ async function testDelete(db: Kysely) { gender: 'male' | 'female' | 'other' modified_at: Date marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null + deleted_at: Date | null name: string owner_id: number @@ -122,9 +122,9 @@ async function testDelete(db: Kysely) { price: number | null pet_id: string | null }[] - >(r10) + >(r3) - const r11 = await db + const r4 = await db .deleteFrom('person') .innerJoin('pet', 'pet.owner_id', 'person.id') .where('pet.species', '=', 'dog') @@ -139,33 +139,33 @@ async function testDelete(db: Kysely) { gender: 'male' | 'female' | 'other' modified_at: Date marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null + deleted_at: Date | null name: string owner_id: number species: 'dog' | 'cat' }[] - >(r11) + >(r4) - const r12 = await db + const r5 = await db .deleteFrom('pet') .where('pet.species', '=', 'cat') .returningAll(['pet']) .execute() - expectType[]>(r12) + expectType[]>(r5) - const r13 = await db + const r6 = await db .deleteFrom('pet') .where('pet.species', '=', 'dog') .returningAll() .execute() - expectType[]>(r13) + expectType[]>(r6) - const r14 = await db + const r7 = await db .deleteFrom('person') .using(['person', 'pet']) .leftJoin('toy', 'toy.pet_id', 'pet.id') .where('pet.species', '=', 'cat') - .orWhere('toy.price', '=', 0) .returningAll() .execute() expectType< @@ -177,6 +177,7 @@ async function testDelete(db: Kysely) { gender: 'male' | 'female' | 'other' modified_at: Date marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null + deleted_at: Date | null name: string owner_id: number @@ -185,14 +186,14 @@ async function testDelete(db: Kysely) { price: number | null pet_id: string | null }[] - >(r14) + >(r7) - const r15 = await db + const r8 = await db .deleteFrom('person as p') .where('p.first_name', '=', 'Jennifer') .returning('p.id') .executeTakeFirstOrThrow() - expectType<{ id: number }>(r15) + expectType<{ id: number }>(r8) } async function testIf(db: Kysely) { @@ -245,3 +246,61 @@ async function testIf(db: Kysely) { f20?: string }>(r) } + +async function testOutput(db: Kysely) { + const r1 = await db + .deleteFrom('pet') + .outputAll('deleted') + .where('pet.species', '=', 'cat') + .execute() + expectType[]>(r1) + + const r2 = await db + .deleteFrom('person as p') + .output('deleted.id') + .where('p.first_name', '=', 'Jennifer') + .executeTakeFirstOrThrow() + expectType<{ id: number }>(r2) + + const r3 = await db + .deleteFrom('person as p') + .output(['deleted.id', 'deleted.last_name as surname']) + .where('p.first_name', '=', 'Jennifer') + .executeTakeFirstOrThrow() + expectType<{ id: number; surname: string | null }>(r3) + + const r4 = await db + .deleteFrom('person') + .output((eb) => [ + 'deleted.age', + eb + .fn('concat', [ + eb.ref('deleted.first_name'), + sql.lit(' '), + 'deleted.last_name', + ]) + .as('full_name'), + ]) + .where('deleted_at', '<', new Date()) + .executeTakeFirstOrThrow() + expectType<{ age: number; full_name: string }>(r4) + + // Non-existent column + expectError(db.deleteFrom('person').output('deleted.NO_SUCH_COLUMN')) + + // Wrong prefix + expectError(db.deleteFrom('person').output('inserted.id')) + expectError(db.deleteFrom('person').outputAll('inserted')) + + // Non-existent prefix + expectError(db.deleteFrom('person').output('NO_SUCH_PREFIX.id')) + expectError(db.deleteFrom('person').outputAll('NO_SUCH_PREFIX')) + + // table prefix + expectError(db.deleteFrom('person').output('person.id')) + expectError(db.deleteFrom('person').outputAll('person')) + + // No prefix + expectError(db.deleteFrom('person').output('id')) + expectError(db.deleteFrom('person').outputAll()) +} diff --git a/test/typings/test-d/expression.test-d.ts b/test/typings/test-d/expression.test-d.ts index 2b94d6277..8c2180c4b 100644 --- a/test/typings/test-d/expression.test-d.ts +++ b/test/typings/test-d/expression.test-d.ts @@ -1,6 +1,12 @@ -import { expectAssignable, expectNotAssignable, expectError } from 'tsd' +import { + expectAssignable, + expectNotAssignable, + expectError, + expectType, +} from 'tsd' import { Expression, ExpressionBuilder, Kysely, SqlBool } from '..' import { Database } from '../shared' +import { KyselyTypeError } from '../../../dist/cjs/util/type-error' function testExpression(db: Kysely) { const e1: Expression = undefined! @@ -9,64 +15,248 @@ function testExpression(db: Kysely) { expectNotAssignable>(e1) expectAssignable>( - db.selectFrom('person').select('first_name') + db.selectFrom('person').select('first_name'), ) expectNotAssignable>( - db.selectFrom('person').select('first_name') + db.selectFrom('person').select('first_name'), ) expectNotAssignable>( - db.selectFrom('person').select('first_name') + db.selectFrom('person').select('first_name'), ) } -function testExpressionBuilder(eb: ExpressionBuilder) { +async function testExpressionBuilder( + eb: ExpressionBuilder, +) { // Binary expression - expectAssignable>(eb.bxp('age', '+', 1)) + expectAssignable>(eb('age', '+', 1)) // `not` expression - expectAssignable>(eb.not(eb.cmpr('age', '>', 10))) + expectAssignable>(eb.not(eb('age', '>', 10))) // `and` expression with one item expectAssignable>( - eb.and([eb.cmpr('first_name', '=', 'Jennifer')]) + eb.and([eb('first_name', '=', 'Jennifer')]), ) // `and` expression with two items expectAssignable>( eb.and([ - eb.cmpr('first_name', '=', 'Jennifer'), - eb.not(eb.cmpr('last_name', '=', 'Aniston')), - ]) + eb('first_name', '=', 'Jennifer'), + eb.not(eb('last_name', '=', 'Aniston')), + ]), ) // `or` expression with one item expectAssignable>( - eb.or([eb.cmpr('first_name', '=', 'Jennifer')]) + eb.or([eb('first_name', '=', 'Jennifer')]), ) // `or` expression with two items expectAssignable>( eb.or([ - eb.cmpr('first_name', '=', 'Jennifer'), - eb.not(eb.cmpr('last_name', '=', 'Aniston')), - ]) + eb('first_name', '=', 'Jennifer'), + eb.not(eb('last_name', '=', 'Aniston')), + ]), ) + // `or` chain with three items + expectAssignable>( + eb('first_name', '=', 'Jennifer') + .or(eb.not(eb('last_name', '=', 'Aniston'))) + .or('age', '>', 23), + ) + + // `and` chain with three items + expectAssignable>( + eb('first_name', '=', 'Jennifer') + .and(eb.not(eb('last_name', '=', 'Aniston'))) + .and('age', '>', 23), + ) + + // nested `and` and `or` chains. + expectAssignable>( + eb.and([ + eb('age', '=', 1).or('age', '=', 2), + eb('first_name', '=', 'Jennifer').or('first_name', '=', 'Arnold'), + ]), + ) + + expectAssignable>(eb.lit(1)) + expectAssignable>(eb.lit(true)) + expectAssignable>(eb.lit(null)) + + expectAssignable>( + eb.and({ + 'person.age': 10, + first_name: 'Jennifer', + last_name: eb.ref('first_name'), + }), + ) + + expectAssignable>( + eb.or({ + 'person.age': 10, + first_name: 'Jennifer', + last_name: eb.ref('first_name'), + }), + ) + + expectAssignable>( + eb.case().when('age', '=', 10).then(1).else(null).end(), + ) + + expectNotAssignable>( + eb.case().when('age', '=', 10).then(1).else(null).end(), + ) + + expectAssignable>( + eb.case().when('age', '=', 10).then(1).else(null).end().$notNull(), + ) + + expectType< + KyselyTypeError<'or() method can only be called on boolean expressions'> + >(eb('age', '+', 1).or('age', '=', 1)) + + expectType< + KyselyTypeError<'and() method can only be called on boolean expressions'> + >(eb('age', '+', 1).and('age', '=', 1)) + // `neg` expression - expectAssignable>(eb.neg(eb.bxp('age', '+', 10))) + expectAssignable>(eb.neg(eb('age', '+', 10))) // Binary expression in a comparison expression - expectAssignable>(eb.cmpr(eb.bxp('age', '+', 1), '>', 0)) + expectAssignable>(eb(eb('age', '+', 1), '>', 0)) // A custom function call expectAssignable>(eb.fn('upper', ['first_name'])) - expectError(eb.cmpr('not_a_person_column'), '=', 'Jennifer') - expectError(eb.bxp('not_a_person_column'), '=', 'Jennifer') + expectAssignable>(eb.between('age', 10, 20)) + expectAssignable>(eb.betweenSymmetric('age', 10, 20)) + + expectAssignable>(eb.cast('age', 'text')) + expectAssignable>(eb.cast(eb.ref('age'), 'text')) + + expectError(eb('not_a_person_column', '=', 'Jennifer')) + expectError(eb('not_a_person_column', '=', 'Jennifer')) expectError(eb.and([eb.val('not booleanish'), eb.val(true)])) - expectError(eb.and([eb.bxp('age', '+', 1), eb.val(true)])) + expectError(eb.and([eb('age', '+', 1), eb.val(true)])) expectError(eb.or([eb.val('not booleanish'), eb.val(true)])) - expectError(eb.or([eb.bxp('age', '+', 1), eb.val(true)])) + expectError(eb.or([eb('age', '+', 1), eb.val(true)])) + + expectError(eb.and({ unknown_column: 'Jennifer' })) + expectError(eb.and({ age: 'wrong type' })) + + expectError(eb.or({ unknown_column: 'Jennifer' })) + expectError(eb.or({ age: 'wrong type' })) + + // String literals are not allowed. + expectError(eb.lit('foobar')) + + expectError(eb.between('age', 'wrong type', 2)) + expectError(eb.between('age', 1, 'wrong type')) + expectError(eb.betweenSymmetric('age', 'wrong type', 2)) + expectError(eb.betweenSymmetric('age', 1, 'wrong type')) +} + +async function textExpressionBuilderAny( + eb: ExpressionBuilder< + Database & { + actor: { + id: string + movie_earnings: number[] + nicknames: string[] | null + } + }, + 'actor' + >, +) { + expectAssignable>(eb.fn.any('nicknames')) + expectAssignable>(eb.fn.any('movie_earnings')) + expectAssignable>(eb.fn.any(eb.val([1, 2, 3]))) + + expectAssignable>( + eb(eb.val('Jen'), '=', eb.fn.any('nicknames')), + ) + + expectAssignable>( + eb(eb.val(42_000_000), '=', eb.fn.any('movie_earnings')), + ) + + expectAssignable>( + eb(eb.val('cat'), '=', eb.fn.any(eb.selectFrom('pet').select('species'))), + ) + + // Wrong array type + expectError(eb(eb.val('Jen'), '=', eb.fn.any('movie_earnings'))) + + // Not an array + expectError(eb(eb.val('Jen'), '=', eb.fn.any('id'))) +} + +function testExpressionBuilderTuple(db: Kysely) { + db.selectFrom('person') + .selectAll() + .where(({ eb, refTuple, tuple }) => + eb(refTuple('first_name', 'last_name'), 'in', [ + tuple('Jennifer', 'Aniston'), + tuple('Sylvester', 'Stallone'), + ]), + ) + + db.selectFrom('person') + .selectAll() + .where(({ eb, refTuple, selectFrom }) => + eb( + refTuple('first_name', 'last_name'), + 'in', + selectFrom('person') + .select(['first_name', 'last_name']) + .$asTuple('first_name', 'last_name'), + ), + ) + + // Wrong tuple type + expectError( + db + .selectFrom('person') + .where(({ eb, refTuple, tuple }) => + eb(refTuple('first_name', 'last_name'), 'in', [ + tuple('Jennifer', 'Aniston'), + tuple('Sylvester', 1), + ]), + ), + ) + + // Wrong tuple length + expectError( + db + .selectFrom('person') + .where(({ eb, refTuple, tuple }) => + eb(refTuple('first_name', 'last_name'), 'in', [ + tuple('Jennifer', 'Aniston', 'Extra'), + tuple('Sylvester', 'Stallone'), + ]), + ), + ) + + // Not all selected columns provided for $asTuple + expectType< + KyselyTypeError<'$asTuple() call failed: All selected columns must be provided as arguments'> + >( + db + .selectFrom('person') + .select(['first_name', 'last_name', 'age']) + .$asTuple('first_name', 'last_name'), + ) + + // Duplicate column provided for $asTuple + expectError( + db + .selectFrom('person') + .select(['first_name', 'last_name']) + .$asTuple('first_name', 'last_name', 'last_name'), + ) } diff --git a/test/typings/test-d/generic.test-d.ts b/test/typings/test-d/generic.test-d.ts new file mode 100644 index 000000000..77e02a408 --- /dev/null +++ b/test/typings/test-d/generic.test-d.ts @@ -0,0 +1,113 @@ +import { + Kysely, + ExpressionBuilder, + SelectQueryBuilder, + Generated, + Nullable, +} from '..' + +import { expectAssignable, expectType } from 'tsd' +import { Database } from '../shared' + +// TODO: type-checking this is crazy slow. Figure out the cause. +function testSelectQueryBuilderExtends() { + type A = { a: number } + type B = { b: string } + + type T1 = SelectQueryBuilder<{ a: A }, 'a', unknown> + + // This type extends T1 and should be assignable to it. + type T2 = SelectQueryBuilder<{ a: A; b: B }, 'a' | 'b', { a: number }> + + const t2 = {} as T2 + expectAssignable(t2) +} + +// TODO: type-checking this is crazy slow. Figure out the cause. +function testExpressionBuilderExtends() { + type A = { a: number } + type B = { b: string } + + type T1 = ExpressionBuilder<{ a: A }, 'a'> + + // This type extends T1 and should be assignable to it. + type T2 = ExpressionBuilder<{ a: A; b: B }, 'a' | 'b'> + + const t2 = {} as T2 + expectAssignable(t2) +} + +// TODO: type-checking this is crazy slow. Figure out the cause. +function testExpressionBuilderExtendsFuncArg() { + type A = { a: number } + type B = { b: string } + type C = { c: boolean } + + // This type extends T1 and should be assignable to it. + type T2 = ExpressionBuilder<{ a: A; b: B; c: C }, 'a' | 'b' | 'c'> + + function test(eb: ExpressionBuilder<{ a: A; b: B; c: C }, 'b' | 'c'>) { + console.log(eb) + } + + const t2 = {} as T2 + test(t2) +} + +// TODO: type-checking this is crazy slow. Figure out the cause. +async function testGenericSelectHelper() { + type Parent = { id: Generated } + type Person = { id: Generated; parent_id: string } + type Pet = { owner_id: string; name: string } + const db: Kysely<{ person: Person; parent: Parent; pet: Pet }> = undefined! + + function personPetSelect( + eb: ExpressionBuilder< + { + parent: Nullable> + petJoin: Nullable> + }, + 'parent' | 'petJoin' + >, + ) { + return ['parent.id'] as const + } + + const result = await db + .selectFrom('parent') + .leftJoin('person as personJoin', 'personJoin.parent_id', 'parent.id') + .leftJoin('pet as petJoin', 'petJoin.owner_id', 'personJoin.id') + .select(personPetSelect) + .execute() +} + +async function testGenericSelect( + db: Kysely, + table: T, +) { + const r1 = await db.selectFrom(table).select('id').executeTakeFirstOrThrow() + expectAssignable(r1.id) +} + +async function testGenericUpdate(db: Kysely, table: 'pet' | 'movie') { + await db.updateTable(table).set({ id: '123' }).execute() +} + +async function testSelectsInVariable(db: Kysely) { + const selects = [ + 'first_name', + (eb: ExpressionBuilder) => + eb + .selectFrom('pet') + .select('name') + .whereRef('pet.owner_id', '=', 'person.id') + .as('pet_name'), + ] as const + + const r1 = await db + .selectFrom('person') + .select(selects) + .executeTakeFirstOrThrow() + + expectType<{ first_name: string; pet_name: string | null }>(r1) +} diff --git a/test/typings/test-d/if.test-d.ts b/test/typings/test-d/if.test-d.ts new file mode 100644 index 000000000..8c8f0229e --- /dev/null +++ b/test/typings/test-d/if.test-d.ts @@ -0,0 +1,180 @@ +import { Kysely, InsertResult, UpdateResult, DeleteResult } from '..' +import { Database } from '../shared' +import { expectType } from 'tsd' + +async function testIfInSelect(db: Kysely) { + const condition = Math.random() < 0.5 + + // Conditional select + const [r1] = await db + .selectFrom('pet as p') + .select('p.species') + .$if(condition, (qb) => qb.select('id')) + .execute() + + // Conditional inner join + const [r2] = await db + .selectFrom('pet as p') + .select('p.species') + .$if(condition, (qb) => qb.innerJoin('person', 'person.id', 'p.owner_id')) + .execute() + + expectType<{ species: 'dog' | 'cat' }>(r2) + + // Conditional inner join with selection + const [r3] = await db + .selectFrom('pet as p') + .select('p.species') + .$if(condition, (qb) => + qb + .innerJoin('person', 'person.id', 'p.owner_id') + .select('age as person_age'), + ) + .execute() + + expectType<{ species: 'dog' | 'cat'; person_age?: number }>(r3) + + // Conditional left join + const [r4] = await db + .selectFrom('pet as p') + .select('p.species') + .$if(condition, (qb) => qb.leftJoin('person', 'person.id', 'p.owner_id')) + .execute() + + expectType<{ species: 'dog' | 'cat' }>(r4) + + // Conditional left join with selection + const [r5] = await db + .selectFrom('pet as p') + .select('p.species') + .$if(condition, (qb) => + qb + .leftJoin('person', 'person.id', 'p.owner_id') + .select('age as person_age'), + ) + .execute() + + expectType<{ species: 'dog' | 'cat'; person_age?: number | null }>(r5) +} + +async function testIfInInsert(db: Kysely) { + const condition = Math.random() < 0.5 + + // Conditional returning in insert + const [r1] = await db + .insertInto('person') + .values({ first_name: 'Foo', last_name: 'Bar', gender: 'other', age: 0 }) + .$if(condition, (qb) => qb.returning('first_name')) + .execute() + + expectType<{ first_name?: string }>(r1) + + // Conditional additional returning in insert + const [r2] = await db + .insertInto('person') + .values({ first_name: 'Foo', last_name: 'Bar', gender: 'other', age: 0 }) + .returning('first_name') + .$if(condition, (qb) => qb.returning('last_name')) + .execute() + + expectType<{ first_name: string; last_name?: string | null }>(r2) + + // Conditional ingore in insert + const [r3] = await db + .insertInto('person') + .values({ first_name: 'Foo', last_name: 'Bar', gender: 'other', age: 0 }) + .$if(condition, (qb) => qb.ignore()) + .execute() + + expectType(r3) + + // Conditional ignore after returning in insert + const [r4] = await db + .insertInto('person') + .values({ first_name: 'Foo', last_name: 'Bar', gender: 'other', age: 0 }) + .returning('first_name') + .$if(condition, (qb) => qb.ignore()) + .execute() + + expectType<{ first_name: string }>(r4) +} + +async function testIfInUpdate(db: Kysely) { + const condition = Math.random() < 0.5 + + // Conditional returning in update + const [r1] = await db + .updateTable('person') + .set({ last_name: 'Foo' }) + .$if(condition, (qb) => qb.returning('first_name')) + .execute() + + expectType<{ first_name?: string }>(r1) + + // Conditional additional returning in update + const [r2] = await db + .updateTable('person') + .set({ last_name: 'Foo' }) + .returning('first_name') + .$if(condition, (qb) => qb.returning('last_name')) + .execute() + + expectType<{ first_name: string; last_name?: string | null }>(r2) + + // Conditional where in update + const [r3] = await db + .updateTable('person') + .set({ last_name: 'Foo' }) + .$if(condition, (qb) => qb.where('id', '=', 1)) + .execute() + + expectType(r3) + + // Conditional where after returning in update + const [r4] = await db + .updateTable('person') + .set({ last_name: 'Foo' }) + .returning('first_name') + .$if(condition, (qb) => qb.where('id', '=', 1)) + .execute() + + expectType<{ first_name: string }>(r4) +} + +async function testIfInDelete(db: Kysely) { + const condition = Math.random() < 0.5 + + // Conditional returning in delete + const [r1] = await db + .deleteFrom('person') + .$if(condition, (qb) => qb.returning('first_name')) + .execute() + + expectType<{ first_name?: string }>(r1) + + // Conditional additional returning in delete + const [r2] = await db + .deleteFrom('person') + .returning('first_name') + .$if(condition, (qb) => qb.returning('last_name')) + .execute() + + expectType<{ first_name: string; last_name?: string | null }>(r2) + + // Conditional where in delete + const [r3] = await db + .deleteFrom('person') + .$if(condition, (qb) => qb.where('id', '=', 1)) + .execute() + + expectType(r3) + + // Conditional where after returning in delete + const [r4] = await db + .deleteFrom('person') + .returning('first_name') + .$if(condition, (qb) => qb.where('id', '=', 1)) + .execute() + + expectType<{ first_name: string }>(r4) +} diff --git a/test/typings/test-d/index.test-d.ts b/test/typings/test-d/index.test-d.ts index 7b23a0c2b..b4436e93c 100644 --- a/test/typings/test-d/index.test-d.ts +++ b/test/typings/test-d/index.test-d.ts @@ -7,258 +7,10 @@ * happy, but we can catch it here. */ -import { - Kysely, - Transaction, - InsertResult, - UpdateResult, - DeleteResult, - Selectable, - sql, - ExpressionBuilder, -} from '..' +import { Kysely, Transaction, InsertResult, Selectable } from '..' import { Database, Person } from '../shared' -import { expectType, expectError, expectAssignable } from 'tsd' - -async function testConditionalJoinWhere(db: Kysely) { - let qb = db.selectFrom('person') - let petName: string | undefined = 'catto' - let petSpecies: 'cat' | 'dog' | undefined = 'cat' - - if (petName || petSpecies) { - let qb2 = qb.innerJoin('pet', 'person.id', 'pet.owner_id') - - if (petName) { - qb2 = qb2.where('pet.name', '=', petName) - } - - if (petSpecies) { - qb2 = qb2.where('pet.species', '=', petSpecies) - } - - // This is the actual test. The query builder with `pet` - // table joined should still be assignable to the original - // query builder. - qb = qb2 - } - - const res = await qb.selectAll('person').execute() -} - -async function testInsert(db: Kysely) { - const person = { - first_name: 'Jennifer', - last_name: 'Aniston', - gender: 'other' as const, - age: 30, - } - - // Insert one row - const r1 = await db.insertInto('person').values(person).execute() - - expectType(r1) - - // Should be able to leave out nullable columns like last_name - const r2 = await db - .insertInto('person') - .values({ first_name: 'fname', age: 10, gender: 'other' }) - .executeTakeFirst() - - expectType(r2) - - // The result type is correct when executeTakeFirstOrThrow is used - const r3 = await db - .insertInto('person') - .values(person) - .executeTakeFirstOrThrow() - - expectType(r3) - - // Insert values from a CTE - const r4 = await db - .with('foo', (db) => - db.selectFrom('person').select('id').where('person.id', '=', 1) - ) - .insertInto('movie') - .values({ - stars: (eb) => eb.selectFrom('foo').select('foo.id'), - }) - .executeTakeFirst() - - expectType(r4) - - // Insert with an on conflict statement - const r5 = await db - .insertInto('person') - .values(person) - .onConflict((oc) => - oc.column('id').doUpdateSet({ - // Should be able to reference the `excluded` "table" - first_name: (eb) => eb.ref('excluded.first_name'), - last_name: (eb) => eb.ref('last_name'), - }) - ) - .executeTakeFirst() - - expectType(r5) - - // Non-existent table - expectError(db.insertInto('doesnt_exists')) - - // Non-existent column - expectError(db.insertInto('person').values({ not_column: 'foo' })) - - // Wrong type for a column - expectError( - db.insertInto('person').values({ first_name: 10, age: 10, gender: 'other' }) - ) - - // Missing required columns - expectError(db.insertInto('person').values({ first_name: 'Jennifer' })) - - // Explicitly excluded column - expectError(db.insertInto('person').values({ modified_at: new Date() })) - - // Non-existent column in a `doUpdateSet` call. - expectError( - db - .insertInto('person') - .values(person) - .onConflict((oc) => - oc.column('id').doUpdateSet({ - first_name: (eb) => eb.ref('doesnt_exist'), - }) - ) - ) - - // GeneratedAlways column is not allowed to be inserted - expectError(db.insertInto('book').values({ id: 1, name: 'foo' })) - - // Wrong subquery return value type - expectError( - db.insertInto('person').values({ - first_name: 'what', - gender: 'male', - age: (eb) => eb.selectFrom('pet').select('pet.name'), - }) - ) - - // Nullable column as undefined - const insertObject: { - first_name: string - last_name: string | undefined - age: number - gender: 'male' | 'female' | 'other' - } = { - first_name: 'emily', - last_name: 'smith', - age: 25, - gender: 'female', - } - - db.insertInto('person').values(insertObject) -} - -async function testReturning(db: Kysely) { - const person = { - first_name: 'Jennifer', - last_name: 'Aniston', - gender: 'other' as const, - age: 30, - } - - // One returning expression - const r1 = await db - .insertInto('person') - .values(person) - .returning('id') - .executeTakeFirst() - - expectType< - | { - id: number - } - | undefined - >(r1) - - // Multiple returning expressions - const r2 = await db - .insertInto('person') - .values(person) - .returning(['id', 'person.first_name as fn']) - .execute() - - expectType< - { - id: number - fn: string - }[] - >(r2) - - // Non-column reference returning expressions - const r3 = await db - .insertInto('person') - .values(person) - .returning([ - 'id', - sql`concat(first_name, ' ', last_name)`.as('full_name'), - (qb) => qb.selectFrom('pet').select('pet.id').as('sub'), - ]) - .execute() - - expectType< - { - id: number - full_name: string - sub: string | null - }[] - >(r3) - - const r4 = await db - .insertInto('movie') - .values({ stars: 5 }) - .returningAll() - .executeTakeFirstOrThrow() - - expectType<{ - id: string - stars: number - }>(r4) - - // Non-existent column - expectError(db.insertInto('person').values(person).returning('not_column')) -} - -async function testUpdate(db: Kysely) { - const r1 = await db - .updateTable('pet as p') - .where('p.id', '=', '1') - .set({ name: 'Fluffy' }) - .executeTakeFirst() - - expectType(r1) - - // Non-existent column - expectError( - db - .updateTable('pet as p') - .where('p.id', '=', '1') - .set({ not_a_column: 'Fluffy' }) - ) - - // GeneratedAlways column is not allowed to be updated - expectError(db.updateTable('book').set({ id: 1, name: 'foo' })) - - db.updateTable('book').set({ name: 'bar' }) - - // Nullable column as undefined - const mutationObject: { last_name: string | undefined } = { - last_name: 'smith', - } - - db.updateTable('person').set(mutationObject) -} +import { expectType, expectError } from 'tsd' async function testOrderBy(db: Kysely) { const r1 = await db @@ -280,82 +32,6 @@ async function testKyselyAndTransactionTypes(db: Kysely) { db = trx } -async function testWith(db: Kysely) { - const r1 = await db - .with('jennifers', (db) => - db.selectFrom('person').where('first_name', '=', 'Jennifer').selectAll() - ) - .with('female_jennifers', (db) => - db - .selectFrom('jennifers') - .select('first_name') - .where('gender', '=', 'female') - .selectAll('jennifers') - .select(['first_name as fn', 'last_name as ln']) - ) - .selectFrom('female_jennifers') - .select(['fn', 'ln']) - .execute() - - expectType< - { - fn: string - ln: string | null - }[] - >(r1) - - const r2 = await db - .with('jennifers(first_name, ln, gender)', (db) => - db - .selectFrom('person') - .where('first_name', '=', 'Jennifer') - .select(['first_name', 'last_name as ln', 'gender']) - ) - .selectFrom('jennifers') - .select(['first_name', 'ln']) - .execute() - - expectType< - { - first_name: string - ln: string | null - }[] - >(r2) - - const r3 = await db - .withRecursive('jennifers(first_name, ln)', (db) => - db - .selectFrom('person') - .where('first_name', '=', 'Jennifer') - .select(['first_name', 'last_name as ln']) - // Recursive CTE can refer to itself. - .union(db.selectFrom('jennifers').select(['first_name', 'ln'])) - ) - .selectFrom('jennifers') - .select(['first_name', 'ln']) - .execute() - - expectType< - { - first_name: string - ln: string | null - }[] - >(r3) - - // Different columns in expression and CTE name. - expectError( - db - .with('jennifers(first_name, last_name, gender)', (db) => - db - .selectFrom('person') - .where('first_name', '=', 'Jennifer') - .select(['first_name', 'last_name']) - ) - .selectFrom('jennifers') - .select(['first_name', 'last_name']) - ) -} - async function testExecuteTakeFirstOrThrow(db: Kysely) { const r1 = await db .selectFrom('person') @@ -377,170 +53,6 @@ async function testCall(db: Kysely) { expectType<{ species: 'dog' | 'cat'; name: string }>(r1) } -async function testIf(db: Kysely) { - const condition = Math.random() < 0.5 - - // Conditional select - const [r1] = await db - .selectFrom('pet as p') - .select('p.species') - .$if(condition, (qb) => qb.select('name')) - .execute() - - expectType<{ species: 'dog' | 'cat'; name?: string }>(r1) - - // Conditional returning in delete - const [r2] = await db - .deleteFrom('person') - .$if(condition, (qb) => qb.returning('first_name')) - .execute() - - expectType<{ first_name?: string }>(r2) - - // Conditional additional returning in delete - const [r3] = await db - .deleteFrom('person') - .returning('first_name') - .$if(condition, (qb) => qb.returning('last_name')) - .execute() - - expectType<{ first_name: string; last_name?: string | null }>(r3) - - // Conditional where in delete - const [r4] = await db - .deleteFrom('person') - .$if(condition, (qb) => qb.where('id', '=', 1)) - .execute() - - expectType(r4) - - // Conditional where after returning in delete - const [r5] = await db - .deleteFrom('person') - .returning('first_name') - .$if(condition, (qb) => qb.where('id', '=', 1)) - .execute() - - expectType<{ first_name: string }>(r5) - - // Conditional returning in update - const [r6] = await db - .updateTable('person') - .set({ last_name: 'Foo' }) - .$if(condition, (qb) => qb.returning('first_name')) - .execute() - - expectType<{ first_name?: string }>(r6) - - // Conditional additional returning in update - const [r7] = await db - .updateTable('person') - .set({ last_name: 'Foo' }) - .returning('first_name') - .$if(condition, (qb) => qb.returning('last_name')) - .execute() - - expectType<{ first_name: string; last_name?: string | null }>(r7) - - // Conditional where in update - const [r8] = await db - .updateTable('person') - .set({ last_name: 'Foo' }) - .$if(condition, (qb) => qb.where('id', '=', 1)) - .execute() - - expectType(r8) - - // Conditional where after returning in update - const [r9] = await db - .updateTable('person') - .set({ last_name: 'Foo' }) - .returning('first_name') - .$if(condition, (qb) => qb.where('id', '=', 1)) - .execute() - - expectType<{ first_name: string }>(r9) - - // Conditional returning in insert - const [r10] = await db - .insertInto('person') - .values({ first_name: 'Foo', last_name: 'Bar', gender: 'other', age: 0 }) - .$if(condition, (qb) => qb.returning('first_name')) - .execute() - - expectType<{ first_name?: string }>(r10) - - // Conditional additional returning in insert - const [r11] = await db - .insertInto('person') - .values({ first_name: 'Foo', last_name: 'Bar', gender: 'other', age: 0 }) - .returning('first_name') - .$if(condition, (qb) => qb.returning('last_name')) - .execute() - - expectType<{ first_name: string; last_name?: string | null }>(r11) - - // Conditional ingore in insert - const [r12] = await db - .insertInto('person') - .values({ first_name: 'Foo', last_name: 'Bar', gender: 'other', age: 0 }) - .$if(condition, (qb) => qb.ignore()) - .execute() - - expectType(r12) - - // Conditional ignore after returning in insert - const [r13] = await db - .insertInto('person') - .values({ first_name: 'Foo', last_name: 'Bar', gender: 'other', age: 0 }) - .returning('first_name') - .$if(condition, (qb) => qb.ignore()) - .execute() - - expectType<{ first_name: string }>(r13) -} - -async function testGenericSelect( - db: Kysely, - table: T -) { - const r1 = await db.selectFrom(table).select('id').executeTakeFirstOrThrow() - expectAssignable(r1.id) -} - -async function testGenericUpdate(db: Kysely, table: 'pet' | 'movie') { - await db.updateTable(table).set({ id: '123' }).execute() -} - -async function testSelectsInVariable(db: Kysely) { - const selects = [ - 'first_name', - (eb: ExpressionBuilder) => - eb - .selectFrom('pet') - .select('name') - .whereRef('pet.owner_id', '=', 'person.id') - .as('pet_name'), - ] as const - - const r1 = await db - .selectFrom('person') - .select(selects) - .executeTakeFirstOrThrow() - - expectType<{ first_name: string; pet_name: string | null }>(r1) -} - -async function testUntypedKysely(db: Kysely) { - // Kysely instance with `any` DB type still extracts column names. - const r1 = await db - .selectFrom('foo') - .select(['spam', 'bar as baz']) - .executeTakeFirstOrThrow() - - expectType<{ spam: any; baz: any }>(r1) -} - async function testReplace(db: Kysely) { const person = { id: 10, @@ -570,7 +82,7 @@ async function testReplace(db: Kysely) { const r4 = await db .with('foo', (db) => - db.selectFrom('person').select('id').where('person.id', '=', 1) + db.selectFrom('person').select('id').where('person.id', '=', 1), ) .replaceInto('movie') .values({ @@ -591,12 +103,12 @@ async function testReplace(db: Kysely) { expectError( db .replaceInto('person') - .values({ first_name: 10, age: 10, gender: 'other' }) + .values({ first_name: 10, age: 10, gender: 'other' }), ) // Missing required columns expectError( - db.replaceInto('person').values({ age: 5, first_name: 'Jennifer' }) + db.replaceInto('person').values({ age: 5, first_name: 'Jennifer' }), ) // Explicitly excluded column diff --git a/test/typings/test-d/insert.test-d.ts b/test/typings/test-d/insert.test-d.ts new file mode 100644 index 000000000..371b06260 --- /dev/null +++ b/test/typings/test-d/insert.test-d.ts @@ -0,0 +1,270 @@ +import { expectError, expectType } from 'tsd' +import { InsertResult, Kysely, sql } from '..' +import { Database } from '../shared' + +async function testInsert(db: Kysely) { + const person = { + first_name: 'Jennifer', + last_name: 'Aniston', + gender: 'other' as const, + age: 30, + } + + // Insert one row + const r1 = await db.insertInto('person').values(person).execute() + + expectType(r1) + + // Should be able to leave out nullable columns like last_name + const r2 = await db + .insertInto('person') + .values({ first_name: 'fname', age: 10, gender: 'other' }) + .executeTakeFirst() + + expectType(r2) + + // The result type is correct when executeTakeFirstOrThrow is used + const r3 = await db + .insertInto('person') + .values(person) + .executeTakeFirstOrThrow() + + expectType(r3) + + // Insert values from a CTE + const r4 = await db + .with('foo', (db) => + db.selectFrom('person').select('id').where('person.id', '=', 1), + ) + .insertInto('movie') + .values({ + stars: (eb) => eb.selectFrom('foo').select('foo.id'), + }) + .executeTakeFirst() + + expectType(r4) + + // Insert with an on conflict statement + const r5 = await db + .insertInto('person') + .values(person) + .onConflict((oc) => + oc.column('id').doUpdateSet({ + // Should be able to reference the `excluded` "table" + first_name: (eb) => eb.ref('excluded.first_name'), + last_name: (eb) => eb.ref('last_name'), + // `excluded` "table" should take the `UpdateType` of complex columns. + deleted_at: (eb) => eb.ref('excluded.deleted_at'), + }), + ) + .executeTakeFirst() + + expectType(r5) + + const r6 = await db + .insertInto('person') + .values((eb) => ({ + first_name: 'fname', + age: 10, + gender: eb.ref('gender'), + })) + .executeTakeFirst() + + expectType(r6) + + // Non-existent table + expectError(db.insertInto('doesnt_exists')) + + // Non-existent column + expectError( + db.insertInto('person').values({ first_name: 'Foo', not_column: 'foo' }), + ) + + // Wrong type for a column + expectError( + db + .insertInto('person') + .values({ first_name: 10, age: 10, gender: 'other' }), + ) + + // Missing required columns + expectError(db.insertInto('person').values({ first_name: 'Jennifer' })) + + // Explicitly excluded column + expectError(db.insertInto('person').values({ modified_at: new Date() })) + + // Non-existent column in a `doUpdateSet` call. + expectError( + db + .insertInto('person') + .values(person) + .onConflict((oc) => + oc.column('id').doUpdateSet({ + first_name: (eb) => eb.ref('doesnt_exist'), + }), + ), + ) + + // GeneratedAlways column is not allowed to be inserted + expectError(db.insertInto('book').values({ id: 1, name: 'foo' })) + + // Wrong subquery return value type + expectError( + db.insertInto('person').values({ + first_name: 'what', + gender: 'male', + age: (eb) => eb.selectFrom('pet').select('pet.name'), + }), + ) + + // Nullable column as undefined + const insertObject: { + first_name: string + last_name: string | undefined + age: number + gender: 'male' | 'female' | 'other' + } = { + first_name: 'emily', + last_name: 'smith', + age: 25, + gender: 'female', + } + + db.insertInto('person').values(insertObject) +} + +async function testReturning(db: Kysely) { + const person = { + first_name: 'Jennifer', + last_name: 'Aniston', + gender: 'other' as const, + age: 30, + } + + // One returning expression + const r1 = await db + .insertInto('person') + .values(person) + .returning('id') + .executeTakeFirst() + + expectType< + | { + id: number + } + | undefined + >(r1) + + // Multiple returning expressions + const r2 = await db + .insertInto('person') + .values(person) + .returning(['id', 'person.first_name as fn']) + .execute() + + expectType< + { + id: number + fn: string + }[] + >(r2) + + // Non-column reference returning expressions + const r3 = await db + .insertInto('person') + .values(person) + .returning([ + 'id', + sql`concat(first_name, ' ', last_name)`.as('full_name'), + (qb) => qb.selectFrom('pet').select('pet.id').as('sub'), + ]) + .execute() + + expectType< + { + id: number + full_name: string + sub: string | null + }[] + >(r3) + + const r4 = await db + .insertInto('movie') + .values({ stars: 5 }) + .returningAll() + .executeTakeFirstOrThrow() + + expectType<{ + id: string + stars: number + }>(r4) + + // Non-existent column + expectError(db.insertInto('person').values(person).returning('not_column')) +} + +async function testOutput(db: Kysely) { + const person = { + first_name: 'Jennifer', + last_name: 'Aniston', + gender: 'other' as const, + age: 30, + } + + // One returning expression + const r1 = await db + .insertInto('person') + .output('inserted.id') + .values(person) + .executeTakeFirst() + + expectType<{ id: number } | undefined>(r1) + + // Multiple returning expressions + const r2 = await db + .insertInto('person') + .output(['inserted.id', 'inserted.first_name as fn']) + .values(person) + .execute() + + expectType<{ id: number; fn: string }[]>(r2) + + // Non-column reference returning expressions + const r3 = await db + .insertInto('person') + .output([ + 'inserted.id', + sql`concat(inserted.first_name, ' ', inserted.last_name)`.as( + 'full_name' + ), + ]) + .values(person) + .execute() + + expectType<{ id: number; full_name: string }[]>(r3) + + const r4 = await db + .insertInto('movie') + .outputAll('inserted') + .values({ stars: 5 }) + .executeTakeFirstOrThrow() + + expectType<{ id: string; stars: number }>(r4) + + // Non-existent column + expectError( + db.insertInto('person').output('inserted.not_column').values(person) + ) + + // Without prefix + expectError(db.insertInto('person').output('age').values(person)) + expectError(db.insertInto('person').outputAll().values(person)) + + // Non-existent prefix + expectError(db.insertInto('person').output('foo.age').values(person)) + expectError(db.insertInto('person').outputAll('foo').values(person)) + + // Wrong prefix + expectError(db.insertInto('person').output('deleted.age').values(person)) + expectError(db.insertInto('person').outputAll('deleted').values(person)) +} diff --git a/test/typings/test-d/join.test-d.ts b/test/typings/test-d/join.test-d.ts index 51e0e88ef..6f4c0278e 100644 --- a/test/typings/test-d/join.test-d.ts +++ b/test/typings/test-d/join.test-d.ts @@ -20,6 +20,7 @@ async function testJoin(db: Kysely) { gender: 'male' | 'female' | 'other' modified_at: Date marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null + deleted_at: Date | null // Pet columns. name: string @@ -47,7 +48,7 @@ async function testJoin(db: Kysely) { .innerJoin( db.selectFrom('pet').select(['pet.id', 'pet.owner_id as owner']).as('p'), 'p.owner', - 'person.id' + 'person.id', ) .where('p.owner', '>', 2) .selectAll('p') @@ -60,7 +61,7 @@ async function testJoin(db: Kysely) { .selectFrom('person') .innerJoin( (qb) => qb.selectFrom('pet').selectAll('pet').as('p'), - (join) => join.onRef('p.owner_id', '=', 'person.id') + (join) => join.onRef('p.owner_id', '=', 'person.id'), ) .where('p.owner_id', '>', 2) .selectAll('p') @@ -84,6 +85,7 @@ async function testJoin(db: Kysely) { gender: 'male' | 'female' | 'other' modified_at: Date marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null + deleted_at: Date | null // All Pet columns should be nullable because of the left join name: string | null @@ -111,6 +113,7 @@ async function testJoin(db: Kysely) { gender: 'male' | 'female' | 'other' | null modified_at: Date | null marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null + deleted_at: Date | null // All Pet columns should also be nullable because there's another // right join after the Pet join. @@ -140,6 +143,7 @@ async function testJoin(db: Kysely) { gender: 'male' | 'female' | 'other' | null modified_at: Date | null marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null + deleted_at: Date | null name: string | null species: 'dog' | 'cat' | null @@ -157,7 +161,7 @@ async function testJoin(db: Kysely) { // Refer to table that's not joined expectError( - db.selectFrom('person').innerJoin('movie', 'movie.id', 'pet.owner_id') + db.selectFrom('person').innerJoin('movie', 'movie.id', 'pet.owner_id'), ) // Refer to column that doesn't exist @@ -167,7 +171,9 @@ async function testJoin(db: Kysely) { expectError( db .selectFrom('person') - .innerJoin('movie as m', (join) => join.onRef('pet.id', '=', 'person.id')) + .innerJoin('movie as m', (join) => + join.onRef('pet.id', '=', 'person.id'), + ), ) // Refer to table with wrong alias @@ -175,8 +181,8 @@ async function testJoin(db: Kysely) { db .selectFrom('person') .innerJoin('movie as m', (join) => - join.onRef('movie.id', '=', 'person.id') - ) + join.onRef('movie.id', '=', 'person.id'), + ), ) } @@ -238,64 +244,64 @@ async function testManyJoins(db: Kysely) { const r3 = await db .selectFrom('person') .leftJoin('pet as p1', (join) => - join.onRef('p1.owner_id', '=', 'person.id') + join.onRef('p1.owner_id', '=', 'person.id'), ) .leftJoin('pet as p2', (join) => - join.onRef('p2.owner_id', '=', 'person.id') + join.onRef('p2.owner_id', '=', 'person.id'), ) .leftJoin('pet as p3', (join) => - join.onRef('p3.owner_id', '=', 'person.id') + join.onRef('p3.owner_id', '=', 'person.id'), ) .leftJoin('pet as p4', (join) => - join.onRef('p4.owner_id', '=', 'person.id') + join.onRef('p4.owner_id', '=', 'person.id'), ) .leftJoin('pet as p5', (join) => - join.onRef('p5.owner_id', '=', 'person.id') + join.onRef('p5.owner_id', '=', 'person.id'), ) .leftJoin('pet as p6', (join) => - join.onRef('p6.owner_id', '=', 'person.id') + join.onRef('p6.owner_id', '=', 'person.id'), ) .leftJoin('pet as p7', (join) => - join.onRef('p7.owner_id', '=', 'person.id') + join.onRef('p7.owner_id', '=', 'person.id'), ) .leftJoin('pet as p8', (join) => - join.onRef('p8.owner_id', '=', 'person.id') + join.onRef('p8.owner_id', '=', 'person.id'), ) .leftJoin('pet as p9', (join) => - join.onRef('p9.owner_id', '=', 'person.id') + join.onRef('p9.owner_id', '=', 'person.id'), ) .leftJoin('pet as p10', (join) => - join.onRef('p10.owner_id', '=', 'person.id') + join.onRef('p10.owner_id', '=', 'person.id'), ) .leftJoin('pet as p11', (join) => - join.onRef('p11.owner_id', '=', 'person.id') + join.onRef('p11.owner_id', '=', 'person.id'), ) .leftJoin('pet as p12', (join) => - join.onRef('p12.owner_id', '=', 'person.id') + join.onRef('p12.owner_id', '=', 'person.id'), ) .leftJoin('pet as p13', (join) => - join.onRef('p13.owner_id', '=', 'person.id') + join.onRef('p13.owner_id', '=', 'person.id'), ) .leftJoin('pet as p14', (join) => - join.onRef('p14.owner_id', '=', 'person.id') + join.onRef('p14.owner_id', '=', 'person.id'), ) .leftJoin('pet as p15', (join) => - join.onRef('p15.owner_id', '=', 'person.id') + join.onRef('p15.owner_id', '=', 'person.id'), ) .leftJoin('pet as p16', (join) => - join.onRef('p16.owner_id', '=', 'person.id') + join.onRef('p16.owner_id', '=', 'person.id'), ) .leftJoin('pet as p17', (join) => - join.onRef('p17.owner_id', '=', 'person.id') + join.onRef('p17.owner_id', '=', 'person.id'), ) .leftJoin('pet as p18', (join) => - join.onRef('p18.owner_id', '=', 'person.id') + join.onRef('p18.owner_id', '=', 'person.id'), ) .leftJoin('pet as p19', (join) => - join.onRef('p19.owner_id', '=', 'person.id') + join.onRef('p19.owner_id', '=', 'person.id'), ) .leftJoin('pet as p20', (join) => - join.onRef('p20.owner_id', '=', 'person.id') + join.onRef('p20.owner_id', '=', 'person.id'), ) .select(['age', 'last_name']) .executeTakeFirstOrThrow() diff --git a/test/typings/test-d/json-traversal.test-d.ts b/test/typings/test-d/json-traversal.test-d.ts new file mode 100644 index 000000000..15c442d5e --- /dev/null +++ b/test/typings/test-d/json-traversal.test-d.ts @@ -0,0 +1,214 @@ +import { expectError, expectType } from 'tsd' +import { ExpressionBuilder, JSONPathBuilder, Kysely } from '..' +import { Database, PersonMetadata } from '../shared' +import { expect } from 'chai' +import { KyselyTypeError } from '../../../dist/cjs/util/type-error' + +async function testJSONReference(db: Kysely) { + const [r1] = await db + .selectFrom('person_metadata') + .select((eb) => eb.ref('website', '->>$').key('url').as('website_url')) + .execute() + + expectType<{ website_url: string }>(r1) + + const [r2] = await db + .selectFrom('person_metadata') + .select((eb) => eb.ref('nicknames', '->>$').at(0).as('nickname')) + .execute() + + expectType<{ nickname: string | null }>(r2) + + const [r3] = await db + .selectFrom('person_metadata') + .select((eb) => + eb.ref('profile', '->>$').key('auth').key('roles').as('roles'), + ) + .execute() + + expectType<{ roles: string[] }>(r3) + + const [r4] = await db + .selectFrom('person_metadata') + .select((eb) => eb.ref('profile', '->>$').key('tags').at(0).as('main_tag')) + .execute() + + expectType<{ main_tag: string | null }>(r4) + + const [r5] = await db + .selectFrom('person_metadata') + .select((eb) => + eb + .ref('experience', '->>$') + .at(0) + .key('establishment') + .as('establishment'), + ) + .execute() + + expectType<{ establishment: string | null }>(r5) + + const [r6] = await db + .selectFrom('person_metadata') + .select((eb) => + eb.ref('schedule', '->>$').at(0).at(0).as('january_1st_schedule'), + ) + .execute() + + expectType<{ january_1st_schedule: { name: string; time: string }[] | null }>( + r6, + ) + + const [r7] = await db + .selectFrom('person_metadata') + .select((eb) => eb.ref('nicknames', '->>$').at('last').as('nickname')) + .execute() + + expectType<{ nickname: string | null }>(r7) + + const [r8] = await db + .selectFrom('person_metadata') + .select((eb) => eb.ref('nicknames', '->>$').at('#-1').as('nickname')) + .execute() + + expectType<{ nickname: string | null }>(r8) + + const [r9] = await db + .selectFrom('person_metadata') + .select((eb) => eb.ref('record', '->').key('i_dunno_man').as('whatever')) + .execute() + + expectType<{ whatever: string | null }>(r9) + + const [r10] = await db + .selectFrom('person_metadata') + .select((eb) => eb.ref('array', '->').at(0).as('whenever')) + .execute() + + expectType<{ whenever: string | null }>(r10) + + // missing operator + + expectError( + db + .selectFrom('person_metadata') + .select((eb) => eb.ref('experience').at(0).as('alias')), + ) + + expectError( + db + .selectFrom('person_metadata') + .select((eb) => eb.ref('website').key('url').as('alias')), + ) + + // invalid operator + + expectError( + db + .selectFrom('person_metadata') + .select((eb) => + eb.ref('website', 'NO_SUCH_OPERATOR').key('url').as('alias'), + ) + .execute(), + ) + + // use `key` on non-object + + expectError( + db + .selectFrom('person_metadata') + .select((eb) => eb.ref('nicknames', '->>$').key('url').as('alias')) + .execute(), + ) + + expectError( + db + .selectFrom('person_metadata') + .select((eb) => [ + eb.ref('website', '->>').key('url').key('length').as('alias'), + eb.ref('schedule', '->>').key('length').as('alias2'), + ]) + .execute(), + ) + + // use `at` on non-array + + expectError( + db + .selectFrom('person_metadata') + .select((eb) => eb.ref('website', '->>$').at(0).as('alias')) + .execute(), + ) + + expectError( + db + .selectFrom('person_metadata') + .select((eb) => eb.ref('experience', '->>').at(0).at(-1).as('alias')) + .execute(), + ) + + // bad key + + expectError( + db + .selectFrom('person_metadata') + .select((eb) => + eb.ref('website', '->>$').key('NO_SUCH_FIELD').as('alias'), + ) + .execute(), + ) + + // bad index + + expectError( + db + .selectFrom('person_metadata') + .select((eb) => eb.ref('nicknames', '->>$').at('0').as('alias')) + .execute(), + ) + + expectError( + db + .selectFrom('person_metadata') + .select((eb) => eb.ref('nicknames', '->>$').at(0.5).as('alias')) + .execute(), + ) + + expectError( + db + .selectFrom('person_metadata') + .select((eb) => eb.ref('nicknames', '->>$').at('#--1').as('alias')) + .execute(), + ) + + expectError( + db + .selectFrom('person_metadata') + .select((eb) => eb.ref('nicknames', '->>$').at('#-1.5').as('alias')) + .execute(), + ) + + expectError( + db + .selectFrom('person_metadata') + .select((eb) => eb.ref('nicknames', '->>$').at('last ').as('alias')) + .execute(), + ) +} + +async function testJSONPath(eb: ExpressionBuilder) { + expectType>( + eb.jsonPath<'experience'>(), + ) + + expectType>( + eb.jsonPath<'person_metadata.experience'>(), + ) + + expectError(eb.jsonPath('experience')) + expectError(eb.jsonPath('person_metadata.experience')) + expectType< + KyselyTypeError<"You must provide a column reference as this method's $ generic"> + >(eb.jsonPath()) + expectError(eb.jsonPath<'NO_SUCH_COLUMN'>()) +} diff --git a/test/typings/test-d/kysely-any.test-d.ts b/test/typings/test-d/kysely-any.test-d.ts index 18465bd1a..74c849380 100644 --- a/test/typings/test-d/kysely-any.test-d.ts +++ b/test/typings/test-d/kysely-any.test-d.ts @@ -1,53 +1,69 @@ -import { DeleteResult, Kysely, UpdateResult } from '..' +import { DeleteResult, InsertResult, Kysely, UpdateResult } from '..' import { expectType } from 'tsd' async function testKyselyAnySelects(db: Kysely) { const r1 = await db.selectFrom('foo').select('bar').execute() - expectType< - { - bar: any - }[] - >(r1) + expectType<{ bar: any }[]>(r1) const r2 = await db.selectFrom('foo').select(['bar', 'baz']).execute() - expectType< - { - bar: any - baz: any - }[] - >(r2) + expectType<{ bar: any; baz: any }[]>(r2) const r3 = await db.selectFrom('foo').select('foo.bar').execute() - expectType< - { - bar: any - }[] - >(r3) + expectType<{ bar: any }[]>(r3) const r4 = await db .selectFrom('foo') .select(['spam', 'foo.bar', 'foo.baz']) .execute() - expectType< - { - spam: any - bar: any - baz: any - }[] - >(r4) + expectType<{ spam: any; bar: any; baz: any }[]>(r4) const r5 = await db .selectFrom(['foo1', 'foo2']) .select(['spam', 'foo1.bar', 'foo2.baz', 'doesnotexists.fux']) .execute() - expectType< - { - spam: any - bar: any - baz: any - fux: never - }[] - >(r5) + expectType<{ spam: any; bar: any; baz: any; fux: never }[]>(r5) + + const r6 = await db + .selectFrom('foo') + .select((eb) => [ + eb.lit(1).as('baz'), + eb.ref('foo.bar').as('bar'), + eb + .selectFrom('bar') + .select('spam') + .whereRef('foo.id', '=', 'bar.id') + .as('spam'), + ]) + .executeTakeFirstOrThrow() + expectType<{ bar: any; spam: any; baz: 1 }>(r6) +} + +async function testKyselyAnyInserts(db: Kysely) { + const r1 = await db + .insertInto('foo') + .values({ bar: 'baz', spam: 1 }) + .executeTakeFirstOrThrow() + expectType(r1) + + const r2 = await db + .insertInto('foo') + .values({ bar: 'baz', spam: 1 }) + .returning('foo') + .executeTakeFirstOrThrow() + expectType<{ foo: any }>(r2) + + const r3 = await db + .insertInto('foo') + .values({ bar: 'baz', spam: 1 }) + .returning(['foo', 'baz']) + .executeTakeFirstOrThrow() + expectType<{ foo: any; baz: any }>(r3) + + const r4 = await db + .insertInto('foo') + .values((eb) => ({ foo: eb.ref('foo.bar') })) + .executeTakeFirstOrThrow() + expectType(r4) } async function testKyselyAnyUpdates(db: Kysely) { @@ -55,7 +71,6 @@ async function testKyselyAnyUpdates(db: Kysely) { .updateTable('foo') .set({ bar: 'baz', spam: 1 }) .where('foo.eggs', '=', 1) - .orWhere('eggs', '=', 2) .executeTakeFirstOrThrow() expectType(r1) @@ -63,7 +78,7 @@ async function testKyselyAnyUpdates(db: Kysely) { .updateTable('foo as f') .set({ bar: 'baz', spam: 1 }) .where('f.eggs', '=', 1) - .orWhere('eggs', '=', 2) + .where('spam', '=', 2) .executeTakeFirstOrThrow() expectType(r2) @@ -71,31 +86,40 @@ async function testKyselyAnyUpdates(db: Kysely) { .updateTable('foo') .set({ bar: 'baz', spam: 1 }) .where('foo.eggs', '=', 1) - .orWhere('eggs', '=', 2) + .where('spam', '=', 2) .returning(['a', 'b']) .executeTakeFirstOrThrow() expectType<{ a: any; b: any }>(r3) + + const r4 = await db + .updateTable('foo') + .set((eb) => ({ + foo: eb('foo.bar', '=', 1), + })) + .where('foo.eggs', '=', 1) + .executeTakeFirstOrThrow() + expectType(r4) } async function testKyselyAnyDeletes(db: Kysely) { const r1 = await db .deleteFrom('foo') .where('foo.eggs', '=', 1) - .orWhere('eggs', '=', 2) + .where('spam', '=', 2) .executeTakeFirstOrThrow() expectType(r1) const r2 = await db .deleteFrom('foo as f') .where('f.eggs', '=', 1) - .orWhere('eggs', '=', 2) + .where('spam', '=', 2) .executeTakeFirstOrThrow() expectType(r2) const r3 = await db .deleteFrom('foo') .where('foo.eggs', '=', 1) - .orWhere('eggs', '=', 2) + .where('spam', '=', 2) .returning(['a', 'b']) .executeTakeFirstOrThrow() expectType<{ a: any; b: any }>(r3) diff --git a/test/typings/test-d/merge.test-d.ts b/test/typings/test-d/merge.test-d.ts new file mode 100644 index 000000000..bff938a03 --- /dev/null +++ b/test/typings/test-d/merge.test-d.ts @@ -0,0 +1,524 @@ +import { expectError, expectType } from 'tsd' +import { + ExpressionBuilder, + JoinBuilder, + Kysely, + MatchedThenableMergeQueryBuilder, + MergeQueryBuilder, + MergeResult, + NotMatchedThenableMergeQueryBuilder, + Selectable, + UpdateQueryBuilder, + WheneableMergeQueryBuilder, + sql, +} from '..' +import { Database, Person } from '../shared' + +async function testMergeInto(db: Kysely) { + db.mergeInto('person') + db.mergeInto('person as p') + expectError(db.mergeInto('NO_SUCH_TABLE')) + expectError(db.mergeInto('NO_SUCH_TABLE as n')) + expectError(db.mergeInto(['person'])) + expectError(db.mergeInto(['person as p'])) + expectError(db.mergeInto(db.selectFrom('person').selectAll().as('person'))) + expectError( + db.mergeInto((eb: ExpressionBuilder) => + eb.selectFrom('person').selectAll().as('person'), + ), + ) + + expectType>( + db.mergeInto('person'), + ) +} + +async function testUsing(db: Kysely) { + db.mergeInto('person').using('pet', 'pet.owner_id', 'person.id') + db.mergeInto('person as p').using('pet as p2', 'p2.owner_id', 'p.id') + expectError(db.mergeInto('person').using('pet')) + expectError(db.mergeInto('person').using('pet', 'pet')) + expectError(db.mergeInto('person').using('pet', 'pet.NO_SUCH_COLUMN')) + expectError(db.mergeInto('person').using('pet', 'pet.owner_id', 'person')) + expectError( + db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.NO_SUCH_COLUMN'), + ) + expectError( + db + .mergeInto('person') + .using('NO_SUCH_TABLE as n', 'n.owner_id', 'person.id'), + ) + db.mergeInto('person').using('pet', (join) => { + // already tested in join.test-d.ts + expectType>(join) + + return join.onTrue() + }) + + expectType< + WheneableMergeQueryBuilder + >(db.mergeInto('person').using('pet', 'pet.owner_id', 'person.id')) + + expectType( + await db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .executeTakeFirstOrThrow(), + ) +} + +async function testWhenMatched( + baseQuery: WheneableMergeQueryBuilder, +) { + baseQuery.whenMatched() + expectError(baseQuery.whenMatched('age')) + expectError(baseQuery.whenMatchedAnd('age')) + expectError(baseQuery.whenMatchedAnd('NO_SUCH_COLUMN')) + expectError(baseQuery.whenMatchedAnd('age', '>')) + expectError(baseQuery.whenMatchedAnd('age', '>', 'string')) + baseQuery.whenMatchedAnd('age', '>', 2) + expectError(baseQuery.whenMatchedAnd('age', 'NO_SUCH_OPERATOR', 2)) + baseQuery.whenMatchedAnd('person.age', sql`>`, 2) + baseQuery.whenMatchedAnd('pet.species', '>', 'cat') + baseQuery.whenMatchedAnd('age', '>', (eb) => { + expectType>(eb) + return eb.ref('person.age') + }) + expectError( + baseQuery.whenMatchedAnd('age', '>', (eb) => eb.ref('person.first_name')), + ) + baseQuery.whenMatchedAnd((eb) => { + // already tested in many places + expectType>(eb) + return eb.and([]) + }) + expectError(baseQuery.whenMatchedAndRef('age')) + expectError(baseQuery.whenMatchedAndRef('NO_SUCH_COLUMN')) + expectError(baseQuery.whenMatchedAndRef('age', '>')) + expectError(baseQuery.whenMatchedAndRef('age', '>', 'string')) + expectError(baseQuery.whenMatchedAndRef('age', '>', 2)) + baseQuery.whenMatchedAndRef('pet.name', '>', 'person.age') + baseQuery.whenMatchedAndRef('person.age', '>', 'pet.name') + baseQuery.whenMatchedAndRef('age', '>', sql`person.age`) + baseQuery.whenMatchedAndRef('age', sql`>`, 'person.age') + expectError(baseQuery.whenMatchedAndRef('age', 'NO_SUCH_OPERATOR', 'age')) + + type ExpectedReturnType = MatchedThenableMergeQueryBuilder< + Database, + 'person', + 'pet', + 'person' | 'pet', + MergeResult + > + expectType(baseQuery.whenMatched()) + expectType(baseQuery.whenMatchedAnd('age', '>', 2)) + expectType( + baseQuery.whenMatchedAndRef('pet.name', '>', 'person.age'), + ) +} + +async function testWhenNotMatched( + baseQuery: WheneableMergeQueryBuilder, +) { + baseQuery.whenNotMatched() + expectError(baseQuery.whenNotMatched('species')) + expectError(baseQuery.whenNotMatchedAnd('species')) + expectError(baseQuery.whenNotMatchedAnd('NO_SUCH_COLUMN')) + expectError(baseQuery.whenNotMatchedAnd('species', '>')) + expectError(baseQuery.whenNotMatchedAnd('species', '>', 'string')) + expectError(baseQuery.whenNotMatchedAnd('species', '>', 2)) + baseQuery.whenNotMatchedAnd('species', '>', 'dog') + expectError( + baseQuery.whenNotMatchedAnd('species', 'NOT_SUCH_OPERATOR', 'dog'), + ) + // when not matched can only reference the source table's columns. + expectError(baseQuery.whenNotMatchedAnd('age', '>', 'dog')) + baseQuery.whenNotMatchedAnd('species', sql`>`, 'dog') + baseQuery.whenNotMatchedAnd('pet.species', '>', sql<'dog'>`dog`) + baseQuery.whenNotMatchedAnd('species', '>', (eb) => { + // already tested in many places + expectType>(eb) + return eb.ref('pet.species') + }) + expectError( + baseQuery.whenNotMatchedAnd('species', '>', (eb) => eb.ref('pet.owner_id')), + ) + baseQuery.whenNotMatchedAnd((eb) => { + // already tested in many places + expectType>(eb) + return eb.and([]) + }) + expectError(baseQuery.whenNotMatchedAndRef('species')) + expectError(baseQuery.whenNotMatchedAndRef('NO_SUCH_COLUMN')) + expectError(baseQuery.whenNotMatchedAndRef('species', '>')) + expectError(baseQuery.whenNotMatchedAndRef('species', '>', 'string')) + expectError(baseQuery.whenNotMatchedAndRef('species', '>', 2)) + baseQuery.whenNotMatchedAndRef('pet.name', '>', 'pet.species') + // when not matched can only reference the source table's columns. + expectError( + baseQuery.whenNotMatchedAndRef('pet.name', '>', 'person.first_name'), + ) + expectError( + baseQuery.whenNotMatchedAndRef('person.first_name', '>', 'pet.species'), + ) + baseQuery.whenNotMatchedAndRef('species', '>', sql`person.age`) + baseQuery.whenNotMatchedAndRef('species', sql`>`, 'pet.species') + expectError( + baseQuery.whenNotMatchedAndRef('species', 'NO_SUCH_OPERATOR', 'name'), + ) + + type ExpectedReturnType = NotMatchedThenableMergeQueryBuilder< + Database, + 'person', + 'pet', + MergeResult + > + expectType(baseQuery.whenNotMatched()) + expectType( + baseQuery.whenNotMatchedAnd('species', '>', 'dog'), + ) + expectType( + baseQuery.whenNotMatchedAndRef('pet.name', '>', 'pet.species'), + ) +} + +async function testWhenNotMatchedBySource( + baseQuery: WheneableMergeQueryBuilder, +) { + baseQuery.whenNotMatchedBySource() + expectError(baseQuery.whenNotMatchedBySource('age')) + expectError(baseQuery.whenNotMatchedBySourceAnd('age')) + expectError(baseQuery.whenNotMatchedBySourceAnd('NO_SUCH_COLUMN')) + expectError(baseQuery.whenNotMatchedBySourceAnd('age', '>')) + expectError(baseQuery.whenNotMatchedBySourceAnd('age', '>', 'string')) + baseQuery.whenNotMatchedBySourceAnd('age', '>', 2) + expectError( + baseQuery.whenNotMatchedBySourceAnd('age', 'NOT_SUCH_OPERATOR', 'dog'), + ) + // when not matched by source can only reference the target table's columns. + expectError(baseQuery.whenNotMatchedBySourceAnd('species', '>', 'dog')) + baseQuery.whenNotMatchedBySourceAnd('age', sql`>`, 2) + baseQuery.whenNotMatchedBySourceAnd('person.age', '>', sql<2>`2`) + baseQuery.whenNotMatchedBySourceAnd('age', '>', (eb) => { + // already tested in many places + expectType>(eb) + return eb.ref('person.age') + }) + expectError( + baseQuery.whenNotMatchedBySourceAnd('age', '>', (eb) => + eb.ref('person.gender'), + ), + ) + baseQuery.whenNotMatchedBySourceAnd((eb) => { + // already tested in many places + expectType>(eb) + return eb.and([]) + }) + expectError(baseQuery.whenNotMatchedBySourceAndRef('age')) + expectError(baseQuery.whenNotMatchedBySourceAndRef('NO_SUCH_COLUMN')) + expectError(baseQuery.whenNotMatchedBySourceAndRef('age', '>')) + expectError(baseQuery.whenNotMatchedBySourceAndRef('age', '>', 'string')) + expectError(baseQuery.whenNotMatchedBySourceAndRef('age', '>', 2)) + baseQuery.whenNotMatchedBySourceAndRef( + 'person.first_name', + '>', + 'person.last_name', + ) + // when not matched by source can only reference the target table's columns. + expectError( + baseQuery.whenNotMatchedBySourceAndRef( + 'person.first_name', + '>', + 'pet.name', + ), + ) + expectError( + baseQuery.whenNotMatchedBySourceAndRef( + 'pet.name', + '>', + 'person.first_name', + ), + ) + + type ExpectedReturnType = MatchedThenableMergeQueryBuilder< + Database, + 'person', + 'pet', + 'person', + MergeResult + > + expectType(baseQuery.whenNotMatchedBySource()) + expectType( + baseQuery.whenNotMatchedBySourceAnd('age', '>', 2), + ) + expectType( + baseQuery.whenNotMatchedBySourceAndRef( + 'person.first_name', + '>', + 'person.last_name', + ), + ) +} + +async function testThenDelete( + baseQuery: MatchedThenableMergeQueryBuilder< + Database, + 'person', + 'pet', + 'person' | 'pet', + MergeResult + >, +) { + baseQuery.thenDelete() + expectError(baseQuery.thenDelete('person')) + expectError(baseQuery.thenDelete(['person'])) + + expectType< + WheneableMergeQueryBuilder + >(baseQuery.thenDelete()) +} + +async function testThenDoNothing( + matchedBaseQuery: MatchedThenableMergeQueryBuilder< + Database, + 'person', + 'pet', + 'person' | 'pet', + MergeResult + >, + notMatchedBaseQuery: NotMatchedThenableMergeQueryBuilder< + Database, + 'person', + 'pet', + MergeResult + >, +) { + matchedBaseQuery.thenDoNothing() + expectError(matchedBaseQuery.thenDoNothing('person')) + expectError(matchedBaseQuery.thenDoNothing(['person'])) + notMatchedBaseQuery.thenDoNothing() + expectError(notMatchedBaseQuery.thenDoNothing('person')) + expectError(notMatchedBaseQuery.thenDoNothing(['person'])) + + expectType< + WheneableMergeQueryBuilder + >(matchedBaseQuery.thenDoNothing()) + expectType< + WheneableMergeQueryBuilder + >(notMatchedBaseQuery.thenDoNothing()) +} + +async function testThenUpdate( + baseQuery: MatchedThenableMergeQueryBuilder< + Database, + 'person', + 'pet', + 'person' | 'pet', + MergeResult + >, + limitedBaseQuery: MatchedThenableMergeQueryBuilder< + Database, + 'person', + 'pet', + 'person', + MergeResult + >, +) { + expectError(baseQuery.thenUpdate()) + expectError(baseQuery.thenUpdate('person')) + expectError(baseQuery.thenUpdate(['person'])) + expectError(baseQuery.thenUpdate({ age: 2 })) + baseQuery.thenUpdate((ub) => { + expectType>( + ub, + ) + return ub + }) + limitedBaseQuery.thenUpdate((ub) => { + expectType>(ub) + return ub + }) + + baseQuery.thenUpdateSet({ age: 2 }) + expectError(baseQuery.thenUpdateSet({ age: 'not_a_number' })) + baseQuery.thenUpdateSet((eb) => { + expectType>(eb) + return { first_name: eb.ref('pet.name') } + }) + limitedBaseQuery.thenUpdateSet((eb) => { + expectType>(eb) + return { last_name: eb.ref('person.first_name') } + }) + baseQuery.thenUpdateSet('age', 2) + expectError(baseQuery.thenUpdateSet('age', 'not_a_number')) + baseQuery.thenUpdateSet('first_name', (eb) => { + expectType>(eb) + return eb.ref('pet.name') + }) + limitedBaseQuery.thenUpdateSet('last_name', (eb) => { + expectType>(eb) + return eb.ref('person.first_name') + }) + + type ExpectedReturnType = WheneableMergeQueryBuilder< + Database, + 'person', + 'pet', + MergeResult + > + expectType(baseQuery.thenUpdate((ub) => ub)) + expectType(baseQuery.thenUpdateSet({ age: 2 })) + expectType( + baseQuery.thenUpdateSet((eb) => ({ first_name: eb.ref('pet.name') })), + ) + expectType(baseQuery.thenUpdateSet('age', 2)) +} + +async function testThenInsert( + baseQuery: NotMatchedThenableMergeQueryBuilder< + Database, + 'person', + 'pet', + MergeResult + >, +) { + expectError(baseQuery.thenInsertValues()) + expectError(baseQuery.thenInsertValues('person')) + expectError(baseQuery.thenInsertValues(['person'])) + expectError(baseQuery.thenInsertValues({ age: 2 })) + baseQuery.thenInsertValues({ age: 2, first_name: 'Moshe', gender: 'other' }) + expectError( + baseQuery.thenInsertValues({ + age: 'not_a_number', + first_name: 'Moshe', + gender: 'other', + }), + ) + baseQuery.thenInsertValues((eb) => { + expectType>(eb) + return { age: 2, first_name: eb.ref('pet.name'), gender: 'other' } + }) + expectError( + baseQuery.thenInsertValues((eb) => { + expectType>(eb) + return { + age: 'not_a_number', + first_name: eb.ref('pet.name'), + gender: 'other', + } + }), + ) + + expectType< + WheneableMergeQueryBuilder + >( + baseQuery.thenInsertValues({ + age: 2, + first_name: 'Moshe', + gender: 'other', + }), + ) +} + +async function testOutput(db: Kysely) { + // One returning expression + const r1 = await db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenDelete() + .output('deleted.id') + .executeTakeFirst() + + expectType<{ id: number } | undefined>(r1) + + // Multiple returning expressions + const r2 = await db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenDelete() + .output(['deleted.id', 'deleted.first_name as fn']) + .execute() + + expectType<{ id: number; fn: string }[]>(r2) + + // Non-column reference returning expressions + const r3 = await db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenUpdateSet('age', (eb) => eb(eb.ref('age'), '+', 20)) + .output([ + 'inserted.age', + sql`concat(deleted.first_name, ' ', deleted.last_name)`.as( + 'full_name', + ), + ]) + .execute() + + expectType<{ age: number; full_name: string }[]>(r3) + + // Return all columns + const r4 = await db + .mergeInto('person') + .using('pet', 'person.id', 'pet.owner_id') + .whenNotMatched() + .thenInsertValues({ + gender: 'female', + age: 15, + first_name: 'Jane', + }) + .outputAll('inserted') + .executeTakeFirstOrThrow() + + expectType>(r4) + + // Non-existent column + expectError( + db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenDelete() + .output('inserted.not_column'), + ) + + // Without prefix + expectError( + db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenDelete() + .output('age'), + ) + expectError( + db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenDelete() + .outputAll(), + ) + + // Non-existent prefix + expectError( + db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenDelete() + .output('foo.age'), + ) + expectError( + db + .mergeInto('person') + .using('pet', 'pet.owner_id', 'person.id') + .whenMatched() + .thenDelete() + .outputAll('foo'), + ) +} diff --git a/test/typings/test-d/postgres-json.test-d.ts b/test/typings/test-d/postgres-json.test-d.ts index d718892b0..898ffe5c9 100644 --- a/test/typings/test-d/postgres-json.test-d.ts +++ b/test/typings/test-d/postgres-json.test-d.ts @@ -1,8 +1,16 @@ -import { jsonBuildObject, Kysely, jsonArrayFrom, jsonObjectFrom, sql } from '..' -import { Database } from '../shared' +import { + jsonBuildObject, + Kysely, + jsonArrayFrom, + jsonObjectFrom, + sql, + ExpressionBuilder, + Selectable, +} from '..' +import { Database, Pet } from '../shared' import { expectType } from 'tsd' -async function testPostgresJsonb(db: Kysely) { +async function testPostgresJsonSelects(db: Kysely) { const query = db.selectFrom('person').select([ 'person.first_name', @@ -13,7 +21,7 @@ async function testPostgresJsonb(db: Kysely) { .selectFrom('pet') .select(['name', 'species']) .whereRef('owner_id', '=', 'person.id') - .orderBy('pet.name') + .orderBy('pet.name'), ).as('pets'), // Nest the first found dog the person owns. Only select specific fields @@ -26,7 +34,7 @@ async function testPostgresJsonb(db: Kysely) { .whereRef('owner_id', '=', 'person.id') .where('species', '=', 'dog') .orderBy('name') - .limit(1) + .limit(1), ).as('doggo'), // Nest an object that holds the person's formatted name. @@ -49,3 +57,153 @@ async function testPostgresJsonb(db: Kysely) { }[] >(r1) } + +async function testPostgresConditionalJsonSelects(db: Kysely) { + const query = db + .selectFrom('person') + .select(['person.first_name']) + .$if(Math.random() < 0.5, (qb) => qb.select(withPets)) + .$if(Math.random() < 0.5, (qb) => qb.select(withDoggo)) + + const r1 = await query.execute() + + expectType< + { + first_name: string + pets?: { name: string; species: 'dog' | 'cat' }[] + doggo?: { doggo_name: string } | null + }[] + >(r1) +} + +async function testPostgresJsonAgg(db: Kysely) { + const r1 = 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() + + expectType< + { + first_name: string + pets: Selectable[] + }[] + >(r1) + + const r2 = await db + .selectFrom('person') + .select((eb) => [ + 'first_name', + eb + .selectFrom('pet') + .select((eb) => eb.fn.jsonAgg('pet').as('pet')) + .whereRef('pet.owner_id', '=', 'person.id') + .as('pets'), + ]) + .execute() + + expectType< + { + first_name: string + pets: Selectable[] | null + }[] + >(r2) + + const r3 = await db + .selectFrom('person') + .select((eb) => [ + 'first_name', + eb + .selectFrom('pet') + .select((eb) => eb.fn.jsonAgg(eb.table('pet')).as('pet')) + .whereRef('pet.owner_id', '=', 'person.id') + .as('pets'), + ]) + .execute() + + expectType< + { + first_name: string + pets: Selectable[] | null + }[] + >(r3) + + const db2 = db.withTables<{ + acquisition: { + id: number + } + transaction: { + id: number + acquisitionId: number + status: string + } + }>() + + const r4 = await db2 + .selectFrom('acquisition') + .leftJoin('transaction', 'transaction.acquisitionId', 'acquisition.id') + .select(({ ref, fn }) => [ + 'acquisition.id', + fn + .coalesce( + fn + .jsonAgg( + jsonBuildObject({ + id: ref('transaction.id').$notNull(), + status: ref('transaction.status'), + }), + ) + .filterWhere('transaction.id', 'is not', null), + sql`'[]'`, + ) + .as('transactions'), + ]) + .groupBy('acquisition.id') + .executeTakeFirstOrThrow() + + expectType<{ + id: number + transactions: { + id: number + status: string | null + }[] + }>(r4) +} + +async function testPostgresToJson(db: Kysely) { + const r1 = await db + .selectFrom('person') + .innerJoin('pet', 'pet.owner_id', 'person.id') + .select((eb) => ['first_name', eb.fn.toJson('pet').as('pet')]) + .execute() + + expectType< + { + first_name: string + pet: Selectable + }[] + >(r1) +} + +function withPets(eb: ExpressionBuilder) { + return jsonArrayFrom( + eb + .selectFrom('pet') + .select(['name', 'species']) + .whereRef('owner_id', '=', 'person.id') + .orderBy('pet.name'), + ).as('pets') +} + +function withDoggo(eb: ExpressionBuilder) { + return jsonObjectFrom( + eb + .selectFrom('pet') + .select('name as doggo_name') + .whereRef('owner_id', '=', 'person.id') + .where('species', '=', 'dog') + .orderBy('name') + .limit(1), + ).as('doggo') +} diff --git a/test/typings/test-d/select-from.test-d.ts b/test/typings/test-d/select-from.test-d.ts index cf6d44b28..6750257ba 100644 --- a/test/typings/test-d/select-from.test-d.ts +++ b/test/typings/test-d/select-from.test-d.ts @@ -14,6 +14,7 @@ async function testFromSingle(db: Kysely) { gender: 'male' | 'female' | 'other' modified_at: Date marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null + deleted_at: Date | null }>(r1) // Table with alias @@ -30,7 +31,7 @@ async function testFromSingle(db: Kysely) { // Subquery factory const [r4] = await db .selectFrom((eb) => - eb.selectFrom('movie').select('movie.stars as strs').as('m') + eb.selectFrom('movie').select('movie.stars as strs').as('m'), ) .selectAll('m') .execute() @@ -71,13 +72,13 @@ async function testFromSingle(db: Kysely) { .selectFrom((eb2) => eb2 .selectFrom((eb3) => - eb3.selectFrom('movie').select('stars as s').as('m1') + eb3.selectFrom('movie').select('stars as s').as('m1'), ) .select('m1.s as s2') - .as('m2') + .as('m2'), ) .select('m2.s2 as s3') - .as('m3') + .as('m3'), ) .selectAll('m3') .execute() @@ -90,6 +91,9 @@ async function testFromSingle(db: Kysely) { .execute() expectType<{ one: 1 }>(r10) + const [r11] = await db.selectFrom('book').select('id').execute() + expectType<{ id: number }>(r11) + // Should not be able to select animal columns from person. expectError(db.selectFrom('person').select('pet.id')) @@ -98,9 +102,6 @@ async function testFromSingle(db: Kysely) { // Should not be able to start a query against non-existent aliased table. expectError(db.selectFrom('doesnt_exists as de')) - - const [r11] = await db.selectFrom('book').select('id').execute() - expectType<{ id: number }>(r11) } async function testFromMultiple(db: Kysely) { diff --git a/test/typings/test-d/select-no-from.test-d.ts b/test/typings/test-d/select-no-from.test-d.ts new file mode 100644 index 000000000..2d1a35e31 --- /dev/null +++ b/test/typings/test-d/select-no-from.test-d.ts @@ -0,0 +1,31 @@ +import { Kysely, SqlBool, sql } from '..' +import { Database } from '../shared' +import { expectType } from 'tsd' + +async function testSelectNoFrom(db: Kysely) { + const r1 = await db + .selectNoFrom(sql<'bar'>`select 'bar'`.as('foo')) + .executeTakeFirstOrThrow() + expectType<{ foo: 'bar' }>(r1) + + const r2 = await db + .selectNoFrom((eb) => eb(eb.val(1), '=', 1).as('very_useful')) + .executeTakeFirstOrThrow() + expectType<{ very_useful: SqlBool }>(r2) + + const r3 = await db + .selectNoFrom([ + sql<'bar'>`select 'bar'`.as('foo'), + db.selectFrom('pet').select('id').limit(1).as('pet_id'), + ]) + .executeTakeFirstOrThrow() + expectType<{ foo: 'bar'; pet_id: string | null }>(r3) + + const r4 = await db + .selectNoFrom((eb) => [ + eb(eb.val(1), '=', 1).as('very_useful'), + eb.selectFrom('pet').select('id').limit(1).as('pet_id'), + ]) + .executeTakeFirstOrThrow() + expectType<{ very_useful: SqlBool; pet_id: string | null }>(r4) +} diff --git a/test/typings/test-d/select.test-d.ts b/test/typings/test-d/select.test-d.ts index 59133772a..d3b0837e8 100644 --- a/test/typings/test-d/select.test-d.ts +++ b/test/typings/test-d/select.test-d.ts @@ -1,5 +1,13 @@ -import { Expression, Kysely, RawBuilder, Simplify, sql } from '..' -import { Database } from '../shared' +import { + Expression, + Kysely, + NotNull, + RawBuilder, + Selectable, + Simplify, + sql, +} from '..' +import { Database, Person } from '../shared' import { expectType, expectError } from 'tsd' async function testSelectSingle(db: Kysely) { @@ -45,7 +53,7 @@ async function testSelectSingle(db: Kysely) { .selectFrom('movie') .whereRef('movie.id', '=', 'person.id') .select('movie.id') - .as('movie_id') + .as('movie_id'), ) .execute() expectType<{ movie_id: string | null }>(r7) @@ -94,6 +102,103 @@ async function testSelectSingle(db: Kysely) { expectError(qb.select('not_property')) expectError(qb.select('person.not_property')) expectError(qb.select('person.not_property as np')) + + // Narrow Type + type NarrowTarget = + | { queue_id: string; callback_url: null } + | { queue_id: null; callback_url: string } + + const [r15] = await db + .selectFrom('action') + .select(['callback_url', 'queue_id']) + .$narrowType() + .execute() + + // Narrow not null + const [r16] = await db + .selectFrom('action') + .select(['callback_url', 'queue_id']) + .$narrowType<{ callback_url: NotNull }>() + .execute() + + expectType(r16.callback_url) + expectType(r16.queue_id) + + const [r17] = await db + .selectFrom('action') + .select(['callback_url', 'queue_id']) + .$narrowType<{ callback_url: NotNull; queue_id: NotNull }>() + .execute() + + expectType(r17.callback_url) + expectType(r17.queue_id) +} + +async function testSelectAll(db: Kysely) { + // Select all when there's only one table to select from + const r1 = await db.selectFrom('person').selectAll().executeTakeFirstOrThrow() + + expectType>(r1) + + // Select all when there's two tables to select from + const r2 = await db + .selectFrom(['person', 'pet']) + .selectAll() + .executeTakeFirstOrThrow() + + expectType<{ + id: string | number + name: string + first_name: string + last_name: string | null + age: number + gender: 'other' | 'male' | 'female' + marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null + modified_at: Date + owner_id: number + species: 'dog' | 'cat' + deleted_at: Date | null + }>(r2) + + // Select all from a single table when there are two tables to select from + const r3 = await db + .selectFrom(['person', 'pet']) + .selectAll('person') + .executeTakeFirstOrThrow() + + expectType>(r3) + + // Two selectAll('table') calls should accumulate selections. + const [r4] = await db + .selectFrom([ + db.selectFrom('person').select('id as person_id').as('per'), + db.selectFrom('pet').select('id as pet_id').as('pet'), + ]) + .selectAll('per') + .selectAll('pet') + .execute() + + expectType<{ person_id: number; pet_id: string }>(r4) + + // Select all from two tables when there's two tables to select from + const r5 = await db + .selectFrom(['person', 'pet']) + .selectAll(['person', 'pet']) + .executeTakeFirstOrThrow() + + expectType<{ + id: string | number + name: string + first_name: string + last_name: string | null + age: number + gender: 'other' | 'male' | 'female' + marital_status: 'single' | 'married' | 'divorced' | 'widowed' | null + modified_at: Date + owner_id: number + species: 'dog' | 'cat' + deleted_at: Date | null + }>(r5) } async function testSelectMultiple(db: Kysely) { @@ -282,7 +387,7 @@ async function testManyNestedSubqueries(db: Kysely) { .whereRef( 'pet4.owner_id', '=', - 'p4.id' + 'p4.id', ) .select((eb8) => [ 'pet4.id', @@ -292,23 +397,23 @@ async function testManyNestedSubqueries(db: Kysely) { .whereRef( 'p5.id', '=', - 'pet4.owner_id' + 'pet4.owner_id', ) - .select('p5.id') + .select('p5.id'), ).as('owner'), - ]) + ]), ).as('pets'), - ]) + ]), ).as('owner'), - ]) + ]), ).as('pets'), - ]) + ]), ).as('owner'), - ]) + ]), ).as('pets'), - ]) + ]), ).as('owner'), - ]) + ]), ).as('pets'), ]) .executeTakeFirstOrThrow() @@ -341,13 +446,13 @@ async function testManyNestedSubqueries(db: Kysely) { } export function jsonArrayFrom( - expr: Expression + expr: Expression, ): RawBuilder[]> { return sql`(select coalesce(json_agg(agg), '[]') from ${expr} as agg)` } export function jsonObjectFrom( - expr: Expression + expr: Expression, ): RawBuilder | null> { return sql`(select to_json(obj) from ${expr} as obj)` } diff --git a/test/typings/test-d/set-operation.test-d.ts b/test/typings/test-d/set-operation.test-d.ts index cfe4e65f4..250213e35 100644 --- a/test/typings/test-d/set-operation.test-d.ts +++ b/test/typings/test-d/set-operation.test-d.ts @@ -23,13 +23,49 @@ async function testUnion(db: Kysely) { expectType<{ id: number; name: string }>(r2) + // Two subqueries + const r3 = await db + .selectFrom('person') + .select(['id', 'first_name as name']) + .where('id', 'in', [1, 2, 3]) + .union([ + db.selectFrom('pet').select('name').select('owner_id as id'), + db.selectFrom('book').select(['id', 'name']), + ]) + .executeTakeFirstOrThrow() + + expectType<{ id: number; name: string }>(r3) + + // Subquery using a callback + const r4 = await db + .selectFrom('person') + .select(['id', 'first_name as name']) + .where('id', 'in', [1, 2, 3]) + .union((eb) => eb.selectFrom('pet').select('name').select('owner_id as id')) + .executeTakeFirstOrThrow() + + expectType<{ id: number; name: string }>(r4) + + // Two subqueries using a callback + const r5 = await db + .selectFrom('person') + .select(['id', 'first_name as name']) + .where('id', 'in', [1, 2, 3]) + .union((eb) => [ + eb.selectFrom('pet').select('name').select('owner_id as id'), + eb.selectFrom('book').select(['id', 'name']), + ]) + .executeTakeFirstOrThrow() + + expectType<{ id: number; name: string }>(r5) + // Unioned expression has a different type expectError( db .selectFrom('person') .select(['id', 'first_name as name']) .where('id', 'in', [1, 2, 3]) - .union(db.selectFrom('pet').select('name').select('owner_id')) + .union(db.selectFrom('pet').select('name').select('owner_id')), ) } @@ -60,7 +96,7 @@ async function testUnionAll(db: Kysely) { .selectFrom('person') .select(['id', 'first_name as name']) .where('id', 'in', [1, 2, 3]) - .unionAll(db.selectFrom('pet').select('name').select('owner_id')) + .unionAll(db.selectFrom('pet').select('name').select('owner_id')), ) } @@ -91,7 +127,7 @@ async function testIntersect(db: Kysely) { .selectFrom('person') .select(['id', 'first_name as name']) .where('id', 'in', [1, 2, 3]) - .intersect(db.selectFrom('pet').select('name').select('owner_id')) + .intersect(db.selectFrom('pet').select('name').select('owner_id')), ) } @@ -122,7 +158,7 @@ async function testIntersectAll(db: Kysely) { .selectFrom('person') .select(['id', 'first_name as name']) .where('id', 'in', [1, 2, 3]) - .intersectAll(db.selectFrom('pet').select('name').select('owner_id')) + .intersectAll(db.selectFrom('pet').select('name').select('owner_id')), ) } @@ -153,7 +189,7 @@ async function testExcept(db: Kysely) { .selectFrom('person') .select(['id', 'first_name as name']) .where('id', 'in', [1, 2, 3]) - .except(db.selectFrom('pet').select('name').select('owner_id')) + .except(db.selectFrom('pet').select('name').select('owner_id')), ) } @@ -184,6 +220,6 @@ async function testExceptAll(db: Kysely) { .selectFrom('person') .select(['id', 'first_name as name']) .where('id', 'in', [1, 2, 3]) - .exceptAll(db.selectFrom('pet').select('name').select('owner_id')) + .exceptAll(db.selectFrom('pet').select('name').select('owner_id')), ) } diff --git a/test/typings/test-d/update.test-d.ts b/test/typings/test-d/update.test-d.ts new file mode 100644 index 000000000..e4b1ba883 --- /dev/null +++ b/test/typings/test-d/update.test-d.ts @@ -0,0 +1,61 @@ +import { Kysely, UpdateResult } from '..' +import { Database } from '../shared' +import { expectType, expectError } from 'tsd' + +async function testUpdate(db: Kysely) { + const r1 = await db + .updateTable('pet') + .where('id', '=', '1') + .set({ name: 'Fluffy' }) + .executeTakeFirst() + expectType(r1) + + const r2 = await db + .updateTable('pet as p') + .where('p.id', '=', '1') + .set({ name: 'Fluffy' }) + .executeTakeFirst() + expectType(r2) + + const r3 = await db + .updateTable('pet as p') + .where('p.id', '=', '1') + .set((eb) => ({ name: eb.ref('p.id') })) + .executeTakeFirst() + expectType(r3) + + const r4 = await db + .updateTable('pet as p') + .where('p.id', '=', '1') + .set('name', 'Fluffy') + .executeTakeFirst() + expectType(r4) + + // Non-existent column + expectError( + db + .updateTable('pet as p') + .where('p.id', '=', '1') + .set({ name: 'Fluffy', not_a_column: 'not_a_column' }), + ) + + // Non-existent column in a callback + expectError( + db + .updateTable('pet as p') + .where('p.id', '=', '1') + .set((eb) => ({ not_a_column: eb.val('not_a_column') })), + ) + + // GeneratedAlways column is not allowed to be updated + expectError(db.updateTable('book').set({ id: 1, name: 'foo' })) + + db.updateTable('book').set({ name: 'bar' }) + + // Nullable column as undefined + const mutationObject: { last_name: string | undefined } = { + last_name: 'smith', + } + + db.updateTable('person').set(mutationObject) +} diff --git a/test/typings/test-d/where.test-d.ts b/test/typings/test-d/where.test-d.ts index 25a94d862..efad9616e 100644 --- a/test/typings/test-d/where.test-d.ts +++ b/test/typings/test-d/where.test-d.ts @@ -1,4 +1,4 @@ -import { Expression, Kysely, sql } from '..' +import { Expression, Kysely, SqlBool, sql } from '..' import { Database } from '../shared' import { expectError } from 'tsd' @@ -29,58 +29,76 @@ function testWhere(db: Kysely) { db.selectFrom('movie').where( (eb) => eb.selectFrom('person').select('gender'), '=', - 'female' + 'female', ) // Subquery in LHS db.selectFrom('movie').where( (eb) => eb.selectFrom('person').select('gender'), '=', - 'female' + 'female', ) // Nullable subquery in LHS - db.selectFrom('movie').where(({ or, cmpr, and }) => - or([ - cmpr('id', '=', '1'), - and([cmpr('stars', '>', 2), cmpr('stars', '<', 5)]), - ]) + db.selectFrom('movie').where((eb) => + eb.or([ + eb('id', '=', '1'), + eb.and([eb('stars', '>', 2), eb('stars', '<', 5)]), + ]), ) const firstName = 'Jennifer' const lastName = 'Aniston' // Dynamic `and` list in expression builder - db.selectFrom('person').where(({ cmpr, and }) => { - const exprs: Expression[] = [] + db.selectFrom('person').where((eb) => { + const exprs: Expression[] = [] if (firstName) { - exprs.push(cmpr('first_name', '=', firstName)) + exprs.push(eb('first_name', '=', firstName)) } if (lastName) { - exprs.push(cmpr('last_name', '=', lastName)) + exprs.push(eb('last_name', '=', lastName)) } - return and(exprs) + return eb.and(exprs) }) // Subquery in RHS db.selectFrom('movie').where(sql`${'female'}`, '=', (eb) => - eb.selectFrom('person').select('gender') + eb.selectFrom('person').select('gender'), ) // Nullable subquery in RHS db.selectFrom('person').where('first_name', 'in', (eb) => - eb.selectFrom('person').select('last_name') + eb.selectFrom('person').select('last_name'), ) // Raw expression - db.selectFrom('person').where('first_name', '=', sql`'foo'`) + db.selectFrom('person').where('first_name', '=', sql`'foo'`) db.selectFrom('person').where('first_name', '=', sql`'foo'`) db.selectFrom('person').where(sql`whatever`, '=', 1) db.selectFrom('person').where(sql`whatever`, '=', true) db.selectFrom('person').where(sql`whatever`, '=', '1') + // Boolean returning select query + db.selectFrom('person') + .selectAll() + .where( + db + .selectFrom('pet') + .select((eb) => eb('name', '=', 'Doggo').as('is_doggo')), + ) + + // Boolean returning select query using a callback + db.selectFrom('person') + .selectAll() + .where((eb) => + eb + .selectFrom('pet') + .select((eb) => eb('name', '=', 'Doggo').as('is_doggo')), + ) + // List value db.selectFrom('person').where('gender', 'in', ['female', 'male']) @@ -104,12 +122,12 @@ function testWhere(db: Kysely) { // Invalid type for column expectError( - db.selectFrom('person').where('gender', 'in', ['female', 'not_a_gender']) + db.selectFrom('person').where('gender', 'in', ['female', 'not_a_gender']), ) // Invalid type for column expectError( - db.selectFrom('some_schema.movie').where('some_schema.movie.id', '=', 1) + db.selectFrom('some_schema.movie').where('some_schema.movie.id', '=', 1), ) // Invalid type for column @@ -119,8 +137,8 @@ function testWhere(db: Kysely) { .where( (qb) => qb.selectFrom('person').select('gender'), '=', - 'not_a_gender' - ) + 'not_a_gender', + ), ) // Invalid type for column @@ -128,4 +146,20 @@ function testWhere(db: Kysely) { // Invalid type for column expectError(db.selectFrom('person').where(sql`first_name`, '=', 1)) + + // Non-boolean returning select query + expectError( + db + .selectFrom('person') + .selectAll() + .where(db.selectFrom('pet').select('name')), + ) + + // Non-boolean returning select query using a callback + expectError( + db + .selectFrom('person') + .selectAll() + .where((eb) => eb.selectFrom('pet').select('name')), + ) } diff --git a/test/typings/test-d/with.test-d.ts b/test/typings/test-d/with.test-d.ts index 3d02dd7fa..3c199fc62 100644 --- a/test/typings/test-d/with.test-d.ts +++ b/test/typings/test-d/with.test-d.ts @@ -5,7 +5,7 @@ import { expectType, expectError } from 'tsd' async function testWith(db: Kysely) { const r1 = await db .with('jennifers', (db) => - db.selectFrom('person').where('first_name', '=', 'Jennifer').selectAll() + db.selectFrom('person').where('first_name', '=', 'Jennifer').selectAll(), ) .with('female_jennifers', (db) => db @@ -13,7 +13,7 @@ async function testWith(db: Kysely) { .select('first_name') .where('gender', '=', 'female') .selectAll('jennifers') - .select(['first_name as fn', 'last_name as ln']) + .select(['first_name as fn', 'last_name as ln']), ) .selectFrom('female_jennifers') .select(['fn', 'ln']) @@ -31,7 +31,7 @@ async function testWith(db: Kysely) { db .selectFrom('person') .where('first_name', '=', 'Jennifer') - .select(['first_name', 'last_name as ln', 'gender']) + .select(['first_name', 'last_name as ln', 'gender']), ) .selectFrom('jennifers') .select(['first_name', 'ln']) @@ -51,7 +51,7 @@ async function testWith(db: Kysely) { .where('first_name', '=', 'Jennifer') .select(['first_name', 'last_name as ln']) // Recursive CTE can refer to itself. - .union(db.selectFrom('jennifers').select(['first_name', 'ln'])) + .union(db.selectFrom('jennifers').select(['first_name', 'ln'])), ) .selectFrom('jennifers') .select(['first_name', 'ln']) @@ -64,6 +64,68 @@ async function testWith(db: Kysely) { }[] >(r3) + // Using CTE builder. + const r4 = await db + .with( + (cte) => cte('jennifers').materialized(), + (db) => + db + .selectFrom('person') + .where('first_name', '=', 'Jennifer') + .select(['first_name', 'last_name as ln', 'gender']), + ) + .selectFrom('jennifers') + .select(['first_name', 'ln']) + .execute() + + expectType< + { + first_name: string + ln: string | null + }[] + >(r4) + + // https://github.com/kysely-org/kysely/issues/785 + const r5 = await db + .with('person_projection', (qb) => + qb + .selectFrom('person') + .select(['first_name', 'last_name']) + .$if(true, (qb) => qb.where('first_name', 'is not', null)), + ) + .selectFrom('person_projection') + .selectAll() + .$if(true, (qb) => qb.where('first_name', 'is not', null)) + .execute() + + expectType< + { + first_name: string + last_name: string | null + }[] + >(r5) + + // testing fix of https://github.com/kysely-org/kysely/issues/785 didn't break $if that adds columns to the projection. + const r6 = await db + .with('person_projection', (qb) => + qb + .selectFrom('person') + .select(['first_name', 'last_name']) + .$if(true, (qb) => qb.select('age')), + ) + .selectFrom('person_projection') + .selectAll() + .$if(true, (qb) => qb.where('first_name', 'is not', null)) + .execute() + + expectType< + { + first_name: string + last_name: string | null + age: number | undefined + }[] + >(r6) + // Different columns in expression and CTE name. expectError( db @@ -71,10 +133,26 @@ async function testWith(db: Kysely) { db .selectFrom('person') .where('first_name', '=', 'Jennifer') - .select(['first_name', 'last_name']) + .select(['first_name', 'last_name']), ) .selectFrom('jennifers') - .select(['first_name', 'last_name']) + .select(['first_name', 'last_name']), + ) + + // Unknown CTE name when using the CTE builder. + expectError( + db + .with( + (cte) => cte('jennifers').materialized(), + (db) => + db + .selectFrom('person') + .where('first_name', '=', 'Jennifer') + .select(['first_name', 'last_name as ln', 'gender']), + ) + .selectFrom('lollifers') + .select(['first_name', 'ln']) + .execute(), ) }