Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
[![Bluesky](https://img.shields.io/badge/Bluesky-0285FF?style=flat&logo=Bluesky&logoColor=white)](https://bsky.app/profile/kysely.dev)

###### Get started
[![Postgres](https://img.shields.io/badge/postgres-%23316192.svg?style=flat&logo=postgresql&logoColor=white)](https://kysely.dev/docs/getting-started?dialect=postgresql)
[![MySQL](https://img.shields.io/badge/mysql-4479A1.svg?style=flat&logo=mysql&logoColor=white)](https://kysely.dev/docs/getting-started?dialect=mysql)
[![MicrosoftSQLServer](https://img.shields.io/badge/Microsoft%20SQL%20Server-CC2927?style=flat&logo=microsoft%20sql%20server&logoColor=white)](https://kysely.dev/docs/getting-started?dialect=mssql)
[![SQLite](https://img.shields.io/badge/sqlite-%2307405e.svg?style=flat&logo=sqlite&logoColor=white)](https://kysely.dev/docs/getting-started?dialect=sqlite)
[![PostgreSQL](https://img.shields.io/badge/PostgreSQL-%23316192.svg?style=flat&logo=postgresql&logoColor=white)](https://kysely.dev/docs/getting-started?dialect=postgresql)
[![MySQL](https://img.shields.io/badge/MySQL-4479A1.svg?style=flat&logo=mysql&logoColor=white)](https://kysely.dev/docs/getting-started?dialect=mysql)
[![MSSQL](https://img.shields.io/badge/MSSQL-CC2927?style=flat&logo=microsoft%20sql%20server&logoColor=white)](https://kysely.dev/docs/getting-started?dialect=mssql)
[![SQLite](https://img.shields.io/badge/SQLite-%2307405e.svg?style=flat&logo=sqlite&logoColor=white)](https://kysely.dev/docs/getting-started?dialect=sqlite)
[![PGlite](https://img.shields.io/badge/PGlite-131517.svg?style=flat&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMDAiIGhlaWdodD0iMTgxIiB2aWV3Qm94PSIwIDAgMzQwIDI3MiIgZmlsbD0ibm9uZSI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMjg4IDg4LjA1MDdMMjg4IDIxNS45N0MyODggMjIwLjM5MSAyODQuNDEzIDIyMy45NzUgMjc5Ljk5MSAyMjMuOTdMMjQ3Ljk2OCAyMjMuOTMyQzI0My43MzQgMjIzLjkyNyAyNDAuMjcyIDIyMC42MzQgMjM5Ljk5NSAyMTYuNDcxQzIzOS45OTggMjE2LjMxMyAyNDAgMjE2LjE1NSAyNDAgMjE1Ljk5NkwyMzkuOTk5IDE2Ny45OThDMjM5Ljk5OSAxNTQuNzQ0IDIyOS4yMzkgMTQzLjk5OSAyMTUuOTg0IDE0My45OTlDMjAzLjEzOCAxNDMuOTk5IDE5Mi42MzYgMTMzLjkwNiAxOTIgMTIxLjIxN1Y0OC4wMDk1TDI0OC4wMyA0OC4wNTA3QzI3MC4xMDkgNDguMDY2OSAyODggNjUuOTcwOCAyODggODguMDUwN1pNMTI4IDQ3Ljk5ODNMMTI4IDEwNC4wMjNDMTI4IDExNy4yNzcgMTM4Ljc0NSAxMjguMDIzIDE1MiAxMjguMDIzSDE3NkwxNzYgMTI2LjQxNEMxNzYgMTQ0Ljk2MiAxOTEuMDM2IDE1OS45OTggMjA5LjU4NCAxNTkuOTk4QzIxNy41MzMgMTU5Ljk5OCAyMjMuOTc3IDE2Ni40NDIgMjIzLjk3NyAxNzQuMzkxTDIyMy45NzcgMjE1LjkzMkMyMjMuOTc3IDIxNi4xMjMgMjIzLjk4IDIxNi4zMTMgMjIzLjk4NCAyMTYuNTAzQzIyMy43MjIgMjIwLjY4NSAyMjAuMjQ3IDIyMy45OTYgMjE1Ljk5OSAyMjMuOTk2TDE3NS43MjYgMjIzLjk5NEwxNzYgMTY4LjAzNEMxNzYuMDIyIDE2My42MTYgMTcyLjQ1NyAxNjAuMDE3IDE2OC4wMzkgMTU5Ljk5NUMxNjMuNjIxIDE1OS45NzMgMTYwLjAyMiAxNjMuNTM4IDE2MCAxNjcuOTU2TDE1OS43MjYgMjIzLjk1OUwxNTkuNzI2IDIyMy45OTJMMTExLjkgMjIzLjk4OVYxNjcuOTk1QzExMS45IDE2My41NzcgMTA4LjMxOCAxNTkuOTk1IDEwMy45IDE1OS45OTVDOTkuNDgxNiAxNTkuOTk1IDk1Ljg5OTkgMTYzLjU3NyA5NS44OTk5IDE2Ny45OTVWMjIzLjk4OEw1NS45OTk1IDIyMy45ODZDNTEuNTgxNCAyMjMuOTg1IDQ4IDIyMC40MDQgNDggMjE1Ljk4NlY4Ny45OThDNDggNjUuOTA2NiA2NS45MDg3IDQ3Ljk5NzkgODguMDAwMiA0Ny45OThMMTI4IDQ3Ljk5ODNaTTI1Mi4wNCA5Ni4yMTUzQzI1Mi4wNCA4OS41ODc5IDI0Ni42NjcgODQuMjE1MyAyNDAuMDQgODQuMjE1M0MyMzMuNDEyIDg0LjIxNTMgMjI4LjA0IDg5LjU4NzkgMjI4LjA0IDk2LjIxNTNDMjI4LjA0IDEwMi44NDMgMjMzLjQxMiAxMDguMjE1IDI0MC4wNCAxMDguMjE1QzI0Ni42NjcgMTA4LjIxNSAyNTIuMDQgMTAyLjg0MyAyNTIuMDQgOTYuMjE1M1oiIGZpbGw9IiNGNkY5NUMiLz48L3N2Zz4=)](https://kysely.dev/docs/getting-started?dialect=pglite)
& more!

# [Kysely](https://kysely.dev)
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"devDependencies": {
"@arethetypeswrong/cli": "^0.17.4",
"@ark/attest": "^0.46.0",
"@electric-sql/pglite": "^0.3.5",
"@types/better-sqlite3": "^7.6.13",
"@types/chai": "^5.0.1",
"@types/chai-as-promised": "^8.0.2",
Expand Down
282 changes: 147 additions & 135 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions site/docs/dialects.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ A dialect is the glue between Kysely and the underlying database engine. Check t
| 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 |
| PGlite | https://kysely-org.github.io/kysely-apidoc/classes/PGliteDialect.html |

## Organization dialects

Expand Down
12 changes: 8 additions & 4 deletions site/docs/getting-started/Dialects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ const builtInDialects: BuiltInDialect[] = [
driverDocsURL:
'https://github.com/WiseLibs/better-sqlite3/blob/master/docs/api.md',
},
{
value: 'pglite',
driverDocsURL: 'https://pglite.dev/docs',
},
]

export function Dialects(props: DialectsProps) {
Expand All @@ -61,10 +65,10 @@ export function Dialects(props: DialectsProps) {
it. This requires a <code>Dialect</code> implementation.
<br />
<br />
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{' '}
<Link to="/docs/dialects">"Dialects"</Link>.
There are {builtInDialects.length} built-in dialects for PostgreSQL,
MySQL, Microsoft SQL Server (MSSQL), SQLite, and PGlite. Additionally,
the community has implemented several dialects to choose from. Find out
more at <Link to="/docs/dialects">"Dialects"</Link>.
</p>
<Heading as="h3">Driver installation</Heading>
<p>
Expand Down
11 changes: 11 additions & 0 deletions site/docs/getting-started/Instantiation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,17 @@ const dialect = new ${dialectClassName}({
})`
}

if (dialect === 'pglite') {
const driverImportName = 'PGlite'

return `import { ${driverImportName} } from '${driverNPMPackageName}'
import { Kysely, ${dialectClassName} } from 'kysely'

const dialect = new ${dialectClassName}({
pglite: new ${driverImportName}(),
})`
}

throw new Error(`Unsupported dialect: ${dialect}`)
}

Expand Down
3 changes: 2 additions & 1 deletion site/docs/getting-started/Querying.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export async function deletePerson(id: number) {

return person
}`,
// TODO: Update to use output clause once #687 is completed
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.
Expand Down Expand Up @@ -63,7 +64,7 @@ export async function deletePerson(id: number) {
return person
}`,
sqlite: postgresqlCodeSnippet,
// TODO: Update to use output clause once #687 is completed
pglite: postgresqlCodeSnippet,
}

export function Querying(props: PropsWithDialect) {
Expand Down
24 changes: 13 additions & 11 deletions site/docs/getting-started/Summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,20 @@ import Admonition from '@theme/Admonition'
import CodeBlock from '@theme/CodeBlock'
import Link from '@docusaurus/Link'
import { IUseADifferentDatabase } from './IUseADifferentDatabase'
import {
PRETTY_DIALECT_NAMES,
type Dialect,
type PropsWithDialect,
} from './shared'
import type { Dialect, PropsWithDialect } from './shared'

const dialectSpecificCodeSnippets: Record<Dialect, string> = {
postgresql: ` await db.schema.createTable('person')
const postgresqlCodeSnippet = ` await db.schema.createTable('person')
.addColumn('id', 'serial', (cb) => cb.primaryKey())
.addColumn('first_name', 'varchar', (cb) => cb.notNull())
.addColumn('last_name', 'varchar')
.addColumn('gender', 'varchar(50)', (cb) => cb.notNull())
.addColumn('created_at', 'timestamp', (cb) =>
cb.notNull().defaultTo(sql\`now()\`)
)
.execute()`,
.execute()`

const dialectSpecificCodeSnippets: Record<Dialect, string> = {
postgresql: postgresqlCodeSnippet,
mysql: ` await db.schema.createTable('person')
.addColumn('id', 'integer', (cb) => cb.primaryKey().autoIncrement())
.addColumn('first_name', 'varchar(255)', (cb) => cb.notNull())
Expand Down Expand Up @@ -46,13 +44,17 @@ const dialectSpecificCodeSnippets: Record<Dialect, string> = {
cb.notNull().defaultTo(sql\`current_timestamp\`)
)
.execute()`,
pglite: postgresqlCodeSnippet,
}

const truncateTableSnippet = `await sql\`truncate table \${sql.table('person')}\`.execute(db)`

const dialectSpecificTruncateSnippets: Record<Dialect, string> = {
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)`,
postgresql: truncateTableSnippet,
mysql: truncateTableSnippet,
mssql: truncateTableSnippet,
sqlite: `await sql\`delete from \${sql.table('person')}\`.execute(db)`,
pglite: truncateTableSnippet,
}

export function Summary(props: PropsWithDialect) {
Expand Down
5 changes: 4 additions & 1 deletion site/docs/getting-started/shared.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { ReactNode } from 'react'
import packageJson from '../../package.json'

export type Dialect = 'postgresql' | 'mysql' | 'sqlite' | 'mssql'
export type Dialect = 'postgresql' | 'mysql' | 'sqlite' | 'mssql' | 'pglite'

export type PropsWithDialect<P = {}> = P & {
dialect: Dialect | undefined
Expand Down Expand Up @@ -31,6 +31,7 @@ export const DIALECT_CLASS_NAMES = {
mysql: 'MysqlDialect',
mssql: 'MssqlDialect',
sqlite: 'SqliteDialect',
pglite: 'PGliteDialect',
} as const satisfies Record<Dialect, string>

export const getDriverNPMPackageNames = (
Expand All @@ -41,6 +42,7 @@ export const getDriverNPMPackageNames = (
mysql: 'mysql2',
mssql: 'tedious',
sqlite: 'better-sqlite3',
pglite: '@electric-sql/pglite',
}) as const satisfies Record<Dialect, string>

export const POOL_NPM_PACKAGE_NAMES = {
Expand All @@ -52,6 +54,7 @@ export const PRETTY_DIALECT_NAMES = {
mysql: 'MySQL',
mssql: 'Microsoft SQL Server (MSSQL)',
sqlite: 'SQLite',
pglite: 'PGlite',
} as const satisfies Record<Dialect, string>

export const PRETTY_PACKAGE_MANAGER_NAMES = {
Expand Down
4 changes: 2 additions & 2 deletions site/src/components/SectionFeatures/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ const FeatureList: FeatureItem[] = [
<>
Kysely's community-driven dialect system makes it easy to implement
support for any SQL database without waiting for the core team. It ships
with official dialects for PostgreSQL, MySQL, MS SQL Server, and SQLite
right out of the box.
with official dialects for PostgreSQL, MySQL, MS SQL Server, SQLite, and
PGlite right out of the box.
</>
),
},
Expand Down
1 change: 1 addition & 0 deletions src/dialect/database-introspector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface DatabaseMetadata {
export interface TableMetadata {
readonly name: string
readonly isView: boolean
readonly isForeign: boolean
readonly columns: ColumnMetadata[]
readonly schema?: string
}
Expand Down
4 changes: 4 additions & 0 deletions src/dialect/dialect-adapter-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export abstract class DialectAdapterBase implements DialectAdapter {
return true
}

get supportsMultipleConnections(): boolean {
return true
}

get supportsTransactionalDdl(): boolean {
return false
}
Expand Down
23 changes: 20 additions & 3 deletions src/dialect/dialect-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,45 @@ export interface DialectAdapter {
/**
* Whether or not this dialect supports `if not exists` in creation of tables/schemas/views/etc.
*
* Default is `false`.
*
* 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
readonly supportsCreateIfNotExists?: boolean

/**
* Whether or not this dialect supports multiple connections at the same time.
*
* Default is `true`.
*
* If this is false, Kysely will use a single connection for all database operations.
*/
readonly supportsMultipleConnections?: boolean

/**
* Whether or not this dialect supports transactional DDL.
*
* Default is `false`.
*
* If this is true, migrations are executed inside a transaction.
*/
readonly supportsTransactionalDdl: boolean
readonly supportsTransactionalDdl?: boolean

/**
* Whether or not this dialect supports the `returning` in inserts
* updates and deletes.
*
* Default is `false`.
*/
readonly supportsReturning: boolean
readonly supportsReturning?: boolean

/**
* Whether or not this dialect supports the `output` clause in inserts
* updates and deletes.
*
* Default is `false`.
*/
readonly supportsOutput?: boolean

Expand Down
1 change: 1 addition & 0 deletions src/dialect/mssql/mssql-introspector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export class MssqlIntrospector implements DatabaseIntrospector {
tableDictionary[key] ||
freeze({
columns: [],
isForeign: false,
isView: rawColumn.table_type === 'V ',
name: rawColumn.table_name,
schema: rawColumn.table_schema_name ?? undefined,
Expand Down
3 changes: 3 additions & 0 deletions src/dialect/mysql/mysql-introspector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export class MysqlIntrospector implements DatabaseIntrospector {
'columns.TABLE_NAME',
'columns.TABLE_SCHEMA',
'tables.TABLE_TYPE',
'tables.ENGINE',
'columns.IS_NULLABLE',
'columns.DATA_TYPE',
'columns.EXTRA',
Expand Down Expand Up @@ -83,6 +84,7 @@ export class MysqlIntrospector implements DatabaseIntrospector {
table = freeze({
name: it.TABLE_NAME,
isView: it.TABLE_TYPE === 'VIEW',
isForeign: it.ENGINE === 'FEDERATED',
schema: it.TABLE_SCHEMA,
columns: [],
})
Expand Down Expand Up @@ -116,6 +118,7 @@ interface RawColumnMetadata {
TABLE_NAME: string
TABLE_SCHEMA: string
TABLE_TYPE: string
ENGINE: string
IS_NULLABLE: 'YES' | 'NO'
DATA_TYPE: string
EXTRA: string
Expand Down
19 changes: 19 additions & 0 deletions src/dialect/pglite/pglite-adapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { PostgresAdapter } from '../postgres/postgres-adapter.js'

export class PGliteAdapter extends PostgresAdapter {
override get supportsMultipleConnections(): boolean {
return false
}

async acquireMigrationLock(): Promise<void> {
// PGlite 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<void> {
// PGlite 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.
}
}
67 changes: 67 additions & 0 deletions src/dialect/pglite/pglite-dialect-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import type { DatabaseConnection } from '../../driver/database-connection.js'

/**
* Config for the PGlite dialect.
*/
export interface PGliteDialectConfig {
/**
* Called once when the first query is executed.
*
* This is a Kysely specific feature and does not come from the `@electric-sql/pglite`
* module.
*/
onCreateConnection?: (connection: DatabaseConnection) => Promise<void>

/**
* A PGlite instance or a function that returns one.
*
* If a function is provided, it's called once when the first query is executed.
*
* https://pglite.dev/docs/api#main-constructor
*/
pglite: PGlite | (() => Promise<PGlite>)
}

/**
* This interface is the subset of the PGlite instance that kysely needs.
*
* We don't use the type from `@electric-sql/pglite` here to not have a dependency
* to it.
*
* https://pglite.dev/docs/api
*/
export interface PGlite {
close(): Promise<void>
closed: boolean
query<T>(
query: string,
params?: any[],
options?: PGliteQueryOptions,
): Promise<PGliteQueryResults<T>>
ready: boolean
transaction<T>(callback: (tx: PGliteTransaction) => Promise<T>): Promise<T>
waitReady: Promise<void>
}

export interface PGliteQueryOptions {
blob?: Blob | File
onNotice?: (notice: any) => void
paramTypes?: number[]
parsers?: Record<number, (value: string) => any>
rowMode?: 'array' | 'object'
serializers?: Record<number, (value: any) => string>
}

export interface PGliteQueryResults<T> {
affectedRows?: number
blob?: Blob
fields: {
dataTypeID: number
name: string
}[]
rows: T[]
}

export interface PGliteTransaction extends Pick<PGlite, 'query'> {
rollback(): Promise<void>
}
Loading
Loading