Skip to content

Commit

Permalink
Merge branch 'master' into json-recipe
Browse files Browse the repository at this point in the history
  • Loading branch information
igalklebanov authored Jul 14, 2023
2 parents 2c1bb3e + 57ca6e5 commit b5c605a
Show file tree
Hide file tree
Showing 37 changed files with 4,266 additions and 90 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,6 @@ jobs:

- name: Run esbuild test
run: npm run test:esbuild

- name: Run cloudflare workers test
run: npm run test:cloudflare-workers
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"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: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",
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {

import {
orWhere
} from './0030-or-where'
} from './0040-or-where'

<div style={{ marginBottom: '1em' }}>
<Playground code={orWhere} setupCode={exampleSetup} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {

import {
conditionalWhereCalls
} from './0040-conditional-where-calls'
} from './0050-conditional-where-calls'

<div style={{ marginBottom: '1em' }}>
<Playground code={conditionalWhereCalls} setupCode={exampleSetup} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {

import {
complexWhereClause
} from './0050-complex-where-clause'
} from './0060-complex-where-clause'

<div style={{ marginBottom: '1em' }}>
<Playground code={complexWhereClause} setupCode={exampleSetup} />
Expand Down
6 changes: 3 additions & 3 deletions site/docs/getting-started/Instantiation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ const dialect = new MysqlDialect({
sqlite: (packageManager) =>
isDialectSupported('sqlite', packageManager)
? `import * as SQLite from '${DRIVER_NPM_PACKAGE_NAMES.sqlite}'
import { Kysely, SQLiteDialect } from 'kysely'
import { Kysely, SqliteDialect } from 'kysely'
const dialect = new SQLiteDialect({
const dialect = new SqliteDialect({
database: new SQLite(':memory:'),
})`
: `/* Kysely doesn't support SQLite + ${
Expand All @@ -67,7 +67,7 @@ const dialectClassNames: Record<
postgresql: () => 'PostgresDialect',
mysql: () => 'MysqlDialect',
sqlite: (packageManager) =>
isDialectSupported('sqlite', packageManager) ? 'SQLiteDialect' : null,
isDialectSupported('sqlite', packageManager) ? 'SqliteDialect' : null,
}

export function Instantiation(
Expand Down
114 changes: 73 additions & 41 deletions src/expression/expression-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ 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 {
Expand All @@ -51,10 +52,9 @@ import {
parseValueExpressionOrList,
} 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'

export interface ExpressionBuilder<DB, TB extends keyof DB> {
Expand Down Expand Up @@ -577,15 +577,42 @@ export interface ExpressionBuilder<DB, TB extends keyof DB> {
* ```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(
exprs: ReadonlyArray<Expression<SqlBool>>
): ExpressionWrapper<DB, TB, SqlBool>

and(exprs: Readonly<FilterObject<DB, TB>>): ExpressionWrapper<DB, TB, SqlBool>

/**
* Combines two or more expressions using the logical `or` operator.
*
Expand All @@ -600,7 +627,7 @@ export interface ExpressionBuilder<DB, TB extends keyof DB> {
* ```ts
* db.selectFrom('person')
* .selectAll('person')
* .where((eb) => or([
* .where((eb) => eb.or([
* eb('first_name', '=', 'Jennifer'),
* eb('fist_name', '=', 'Arnold'),
* eb('fist_name', '=', 'Sylvester')
Expand All @@ -612,15 +639,42 @@ export interface ExpressionBuilder<DB, TB extends keyof DB> {
* ```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(
exprs: ReadonlyArray<Expression<SqlBool>>
): ExpressionWrapper<DB, TB, SqlBool>

or(exprs: Readonly<FilterObject<DB, TB>>): ExpressionWrapper<DB, TB, SqlBool>

/**
* Wraps the expression in parentheses.
*
Expand Down Expand Up @@ -812,45 +866,23 @@ export function createExpressionBuilder<DB, TB extends keyof DB>(
},

and(
exprs: ReadonlyArray<Expression<SqlBool>>
exprs: ReadonlyArray<Expression<SqlBool>> | Readonly<FilterObject<DB, TB>>
): ExpressionWrapper<DB, TB, SqlBool> {
if (exprs.length === 0) {
return new ExpressionWrapper(ValueNode.createImmediate(true))
} else if (exprs.length === 1) {
return new ExpressionWrapper(exprs[0].toOperationNode())
}

let node = AndNode.create(
exprs[0].toOperationNode(),
exprs[1].toOperationNode()
)

for (let i = 2; i < exprs.length; ++i) {
node = AndNode.create(node, exprs[i].toOperationNode())
if (isReadonlyArray(exprs)) {
return new ExpressionWrapper(parseFilterList(exprs, 'and'))
}

return new ExpressionWrapper(ParensNode.create(node))
return new ExpressionWrapper(parseFilterObject(exprs, 'and'))
},

or(
exprs: ReadonlyArray<Expression<SqlBool>>
exprs: ReadonlyArray<Expression<SqlBool>> | Readonly<FilterObject<DB, TB>>
): ExpressionWrapper<DB, TB, SqlBool> {
if (exprs.length === 0) {
return new ExpressionWrapper(ValueNode.createImmediate(false))
} else if (exprs.length === 1) {
return new ExpressionWrapper(exprs[0].toOperationNode())
}

let node = OrNode.create(
exprs[0].toOperationNode(),
exprs[1].toOperationNode()
)

for (let i = 2; i < exprs.length; ++i) {
node = OrNode.create(node, exprs[i].toOperationNode())
if (isReadonlyArray(exprs)) {
return new ExpressionWrapper(parseFilterList(exprs, 'or'))
}

return new ExpressionWrapper(ParensNode.create(node))
return new ExpressionWrapper(parseFilterObject(exprs, 'or'))
},

parens(...args: any[]) {
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,5 +244,6 @@ export {
ComparisonOperatorExpression,
OperandValueExpression,
OperandValueExpressionOrList,
FilterObject,
} from './parser/binary-operation-parser.js'
export { ExistsExpression } from './parser/unary-operation-parser.js'
16 changes: 16 additions & 0 deletions src/operation-node/common-table-expression-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -26,4 +32,14 @@ export const CommonTableExpressionNode = freeze({
expression,
})
},

cloneWith(
node: CommonTableExpressionNode,
props: CommonTableExpressionNodeProps
): CommonTableExpressionNode {
return freeze({
...node,
...props,
})
},
})
1 change: 1 addition & 0 deletions src/operation-node/operation-node-transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ export class OperationNodeTransformer {
return requireAllProps<CommonTableExpressionNode>({
kind: 'CommonTableExpressionNode',
name: this.transformNode(node.name),
materialized: node.materialized,
expression: this.transformNode(node.expression),
})
}
Expand Down
Loading

0 comments on commit b5c605a

Please sign in to comment.