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
6 changes: 3 additions & 3 deletions src/query-builder/select-query-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1847,7 +1847,7 @@ export interface SelectQueryBuilder<DB, TB extends keyof DB, O>
*/
$if<O2>(
condition: boolean,
func: (qb: this) => SelectQueryBuilder<any, any, O & O2>,
func: (qb: this) => SelectQueryBuilderExpression<O & O2>,
): SelectQueryBuilder<DB, TB, O & Partial<Omit<O2, keyof O>>>

/**
Expand Down Expand Up @@ -2589,10 +2589,10 @@ class SelectQueryBuilderImpl<

$if<O2>(
condition: boolean,
func: (qb: this) => SelectQueryBuilder<any, any, O & O2>,
func: (qb: this) => SelectQueryBuilderExpression<O & O2>,
): SelectQueryBuilder<DB, TB, O & Partial<Omit<O2, keyof O>>> {
if (condition) {
return func(this)
return func(this) as any
}

return new SelectQueryBuilderImpl({
Expand Down
14 changes: 14 additions & 0 deletions test/ts-benchmarks/generic.bench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
DeleteQueryBuilder,
ExpressionBuilder,
Generated,
InsertQueryBuilder,
Kysely,
MergeQueryBuilder,
Nullable,
Expand Down Expand Up @@ -77,6 +78,15 @@ declare function acceptsNarrowDeleteQueryBuilder(
qb: DeleteQueryBuilder<{ a: A; b: B }, 'a', unknown>,
): void

declare const wideInsertQueryBuilder: InsertQueryBuilder<
{ a: A; b: B },
'a',
{ a: number }
>
declare function acceptsNarrowInsertQueryBuilder(
qb: InsertQueryBuilder<{ a: A; b: B }, 'a', unknown>,
): void

declare const wideUpdateQueryBuilder: UpdateQueryBuilder<
{ a: A; b: B },
'a',
Expand Down Expand Up @@ -164,6 +174,10 @@ bench('DeleteQueryBuilder assignable to narrower DeleteQueryBuilder', () => {
return acceptsNarrowDeleteQueryBuilder(wideDeleteQueryBuilder)
}).types([10919, 'instantiations'])

bench('InsertQueryBuilder assignable to narrower InsertQueryBuilder', () => {
return acceptsNarrowInsertQueryBuilder(wideInsertQueryBuilder)
}).types([2614, 'instantiations'])

bench('UpdateQueryBuilder assignable to narrower UpdateQueryBuilder', () => {
return acceptsNarrowUpdateQueryBuilder(wideUpdateQueryBuilder)
}).types([91178, 'instantiations'])
Expand Down
102 changes: 102 additions & 0 deletions test/ts-benchmarks/if.bench.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { bench } from '@ark/attest'
import type { DB } from '../typings/test-d/huge-db.test-d.js'
import type { Kysely } from '../../dist/index.js'

// `$if` is how conditional filters, optional selections and optional joins get
// built in application code, so it tends to appear in every non-trivial query.
//
// Each of these numbers includes the one-time cost of relating two
// instantiations of the builder under test, because that is what a `$if` call
// site makes the compiler do: it has to match the callback's return type
// against the builder type in the signature. Keep the callback return types
// pointed at the smallest interface that still identifies the builder - see the
// comment on `SelectQueryBuilder.$if`.

declare const kysely: Kysely<DB>
declare const condition: boolean

console.log('if.bench.ts:\n')

bench.baseline(() => {})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's probably better to:

Suggested change
bench.baseline(() => {})
bench.baseline(() => {
return kysely.selectFrom('my_table').select('my_table.id')
})


bench('kysely..select..$if(qb => qb.select(column))', () => {
return kysely
.selectFrom('my_table')
.select('my_table.id')
.$if(condition, (qb) =>
qb.select('my_table.col_2e66a5c7e24d1d066230f368ce8b094e'),
)
}).types([7027, 'instantiations'])

bench('kysely..select..$if(qb => qb.where(...))', () => {
return kysely
.selectFrom('my_table')
.select('my_table.id')
.$if(condition, (qb) =>
qb.where('my_table.col_1d726898491fbca9a8dac855d2be1be8', '=', 1),
)
}).types([3509, 'instantiations'])

bench('kysely..select..$if(qb => qb.innerJoin(...))', () => {
return kysely
.selectFrom('my_table')
.select('my_table.id')
.$if(condition, (qb) =>
qb.innerJoin(
'table_0b5ac72e03509e06683edcba4b3887ab',
'table_0b5ac72e03509e06683edcba4b3887ab.id',
'my_table.id',
),
)
}).types([8742, 'instantiations'])

bench('kysely..select..$if x3', () => {
return kysely
.selectFrom('my_table')
.select('my_table.id')
.$if(condition, (qb) =>
qb.where('my_table.col_1d726898491fbca9a8dac855d2be1be8', '=', 1),
)
.$if(condition, (qb) =>
qb.select('my_table.col_2e66a5c7e24d1d066230f368ce8b094e'),
)
.$if(condition, (qb) =>
qb.select('my_table.col_4f84013a8b5e4c2b7529058c8fafcaa8'),
)
}).types([10196, 'instantiations'])

bench('kysely..update..$if(qb => qb.returning(column))', () => {
return kysely
.updateTable('my_table')
.set('my_table.col_2e66a5c7e24d1d066230f368ce8b094e', 'x')
.returning('my_table.id')
.$if(condition, (qb) =>
qb.returning('my_table.col_2e66a5c7e24d1d066230f368ce8b094e'),
)
}).types([27600, 'instantiations'])

bench('kysely..delete..$if(qb => qb.returning(column))', () => {
return kysely
.deleteFrom('my_table')
.returning('my_table.id')
.$if(condition, (qb) =>
qb.returning('my_table.col_2e66a5c7e24d1d066230f368ce8b094e'),
)
}).types([12710, 'instantiations'])

bench('kysely..insert..$if(qb => qb.returning(column))', () => {
return kysely
.insertInto('my_table')
.defaultValues()
.returning('my_table.id')
.$if(condition, (qb) =>
qb.returning('my_table.col_2e66a5c7e24d1d066230f368ce8b094e'),
)
}).types([4083, 'instantiations'])

bench('kysely..$call(qb => qb.select(column))', () => {
return kysely
.selectFrom('my_table')
.select('my_table.id')
.$call((qb) => qb.select('my_table.col_2e66a5c7e24d1d066230f368ce8b094e'))
}).types([968, 'instantiations'])
125 changes: 125 additions & 0 deletions test/ts-benchmarks/insert-values.bench.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { bench } from '@ark/attest'
import type { DB } from '../typings/test-d/huge-db.test-d.js'
import type { Kysely } from '../../dist/index.js'

// `insert-into.bench.ts` only covers picking the table. These cover the parts
// that carry data - the values themselves, upserts and `set` - which is where a
// row type gets matched against the table's insertable columns. Bulk inserts
// are worth watching in particular: the cost should stay flat in the number of
// rows, since every row is checked against the same type.

declare const kysely: Kysely<DB>
declare const kyselyAny: Kysely<any>

const row = {
col_1d726898491fbca9a8dac855d2be1be8: 1,
col_2e66a5c7e24d1d066230f368ce8b094e: 'a',
col_2f76db193eac6ad0f152563313673ac9: new Date(),
col_4f84013a8b5e4c2b7529058c8fafcaa8: 'b',
col_d2508118d0d39e198d1129d87d692d59: new Date(),
col_454ff479a3b5a9ef082d9be9ac02a6f4: 'c',
col_3917508388f24a50271f7088b657123c: 'd',
}

declare const rows: (typeof row)[]

console.log('insert-values.bench.ts:\n')

bench.baseline(() => {
return kysely.insertInto('my_table')
})

bench('kysely.insertInto(table).values(row)', () => {
return kysely.insertInto('my_table').values(row)
}).types([1038, 'instantiations'])

bench('kysely.insertInto(table).values(~row)', () => {
// @ts-expect-error
return kysely.insertInto('my_table').values({ ...row, no_such_column: 1 })
}).types([1171, 'instantiations'])

bench('kysely.insertInto(table).values([row])', () => {
return kysely.insertInto('my_table').values([row])
}).types([1047, 'instantiations'])

bench('kysely.insertInto(table).values([row x5])', () => {
return kysely.insertInto('my_table').values([row, row, row, row, row])
}).types([1047, 'instantiations'])

bench('kysely.insertInto(table).values([row x10])', () => {
return kysely
.insertInto('my_table')
.values([row, row, row, row, row, row, row, row, row, row])
}).types([1047, 'instantiations'])

bench('kysely.insertInto(table).values(row[])', () => {
return kysely.insertInto('my_table').values(rows)
}).types([1045, 'instantiations'])

bench('kysely.insertInto(table).values(eb => row)', () => {
return kysely.insertInto('my_table').values((eb) => ({
...row,
col_1d726898491fbca9a8dac855d2be1be8: eb
.selectFrom('my_table as t2')
.select('t2.col_1d726898491fbca9a8dac855d2be1be8')
.limit(1),
}))
}).types([2522, 'instantiations'])

bench('kysely..onConflict(oc => oc.column(column).doNothing())', () => {
return kysely
.insertInto('my_table')
.values(row)
.onConflict((oc) =>
oc.column('col_1d726898491fbca9a8dac855d2be1be8').doNothing(),
)
}).types([1102, 'instantiations'])

bench('kysely..onConflict(oc => oc.column(column).doUpdateSet(row))', () => {
return kysely
.insertInto('my_table')
.values(row)
.onConflict((oc) =>
oc.column('col_1d726898491fbca9a8dac855d2be1be8').doUpdateSet(row),
)
}).types([2131, 'instantiations'])

bench('kysely..onConflict(oc => oc..doUpdateSet(eb => excluded ref))', () => {
return kysely
.insertInto('my_table')
.values(row)
.onConflict((oc) =>
oc.column('col_1d726898491fbca9a8dac855d2be1be8').doUpdateSet({
col_2e66a5c7e24d1d066230f368ce8b094e: (eb) =>
eb.ref('excluded.col_2e66a5c7e24d1d066230f368ce8b094e'),
}),
)
}).types([4458, 'instantiations'])

bench('kysely.updateTable(table).set(row)', () => {
return kysely.updateTable('my_table').set(row)
}).types([848, 'instantiations'])

bench('kysely.updateTable(table).set(column, value)', () => {
return kysely
.updateTable('my_table')
.set('my_table.col_2e66a5c7e24d1d066230f368ce8b094e', 'x')
}).types([3078, 'instantiations'])

bench('kysely.updateTable(table).set(eb => row)', () => {
return kysely.updateTable('my_table').set((eb) => ({
col_1d726898491fbca9a8dac855d2be1be8: eb(
'col_1d726898491fbca9a8dac855d2be1be8',
'+',
1,
),
}))
}).types([3520, 'instantiations'])
Comment on lines +99 to +117

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these don't belong in this bench.


bench('kyselyAny.insertInto(table).values(row)', () => {
return kyselyAny.insertInto('my_table').values(row)
}).types([421, 'instantiations'])

bench('kyselyAny.updateTable(table).set(row)', () => {
return kyselyAny.updateTable('my_table').set(row)
}).types([333, 'instantiations'])
Comment on lines +123 to +125

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't belong in this bench.

Loading
Loading