kysely 0.19.12 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/dialect/mysql/mysql-introspector.js +2 -0
  3. package/dist/cjs/dialect/mysql/mysql-query-compiler.d.ts +5 -0
  4. package/dist/cjs/dialect/mysql/mysql-query-compiler.js +16 -0
  5. package/dist/cjs/dialect/postgres/postgres-introspector.js +7 -1
  6. package/dist/cjs/dialect/postgres/postgres-query-compiler.d.ts +1 -3
  7. package/dist/cjs/dialect/postgres/postgres-query-compiler.js +3 -8
  8. package/dist/cjs/dialect/sqlite/sqlite-introspector.js +2 -0
  9. package/dist/cjs/dialect/sqlite/sqlite-query-compiler.d.ts +3 -0
  10. package/dist/cjs/dialect/sqlite/sqlite-query-compiler.js +10 -0
  11. package/dist/cjs/index.d.ts +2 -0
  12. package/dist/cjs/index.js +2 -0
  13. package/dist/cjs/operation-node/create-table-node.d.ts +6 -1
  14. package/dist/cjs/operation-node/create-table-node.js +16 -0
  15. package/dist/cjs/operation-node/delete-query-node.d.ts +3 -0
  16. package/dist/cjs/operation-node/delete-query-node.js +6 -0
  17. package/dist/cjs/operation-node/explain-node.d.ts +16 -0
  18. package/dist/cjs/operation-node/explain-node.js +19 -0
  19. package/dist/cjs/operation-node/insert-query-node.d.ts +2 -0
  20. package/dist/cjs/operation-node/operation-node-transformer.d.ts +2 -0
  21. package/dist/cjs/operation-node/operation-node-transformer.js +14 -0
  22. package/dist/cjs/operation-node/operation-node-visitor.d.ts +2 -0
  23. package/dist/cjs/operation-node/operation-node-visitor.js +1 -0
  24. package/dist/cjs/operation-node/operation-node.d.ts +1 -1
  25. package/dist/cjs/operation-node/select-query-node.d.ts +3 -0
  26. package/dist/cjs/operation-node/select-query-node.js +6 -0
  27. package/dist/cjs/operation-node/update-query-node.d.ts +3 -0
  28. package/dist/cjs/operation-node/update-query-node.js +6 -0
  29. package/dist/cjs/query-builder/delete-query-builder.d.ts +19 -1
  30. package/dist/cjs/query-builder/delete-query-builder.js +24 -0
  31. package/dist/cjs/query-builder/function-builder.d.ts +3 -3
  32. package/dist/cjs/query-builder/insert-query-builder.d.ts +20 -2
  33. package/dist/cjs/query-builder/insert-query-builder.js +26 -0
  34. package/dist/cjs/query-builder/select-query-builder.d.ts +38 -1
  35. package/dist/cjs/query-builder/select-query-builder.js +45 -2
  36. package/dist/cjs/query-builder/update-query-builder.d.ts +20 -1
  37. package/dist/cjs/query-builder/update-query-builder.js +25 -0
  38. package/dist/cjs/query-compiler/default-query-compiler.d.ts +6 -0
  39. package/dist/cjs/query-compiler/default-query-compiler.js +58 -3
  40. package/dist/cjs/raw-builder/sql.d.ts +96 -96
  41. package/dist/cjs/raw-builder/sql.js +0 -96
  42. package/dist/cjs/schema/create-table-builder.d.ts +54 -0
  43. package/dist/cjs/schema/create-table-builder.js +64 -0
  44. package/dist/cjs/util/explainable.d.ts +5 -0
  45. package/dist/cjs/util/explainable.js +2 -0
  46. package/dist/esm/dialect/mysql/mysql-introspector.js +2 -0
  47. package/dist/esm/dialect/mysql/mysql-query-compiler.d.ts +5 -0
  48. package/dist/esm/dialect/mysql/mysql-query-compiler.js +16 -0
  49. package/dist/esm/dialect/postgres/postgres-introspector.js +7 -1
  50. package/dist/esm/dialect/postgres/postgres-query-compiler.d.ts +1 -3
  51. package/dist/esm/dialect/postgres/postgres-query-compiler.js +3 -8
  52. package/dist/esm/dialect/sqlite/sqlite-introspector.js +2 -0
  53. package/dist/esm/dialect/sqlite/sqlite-query-compiler.d.ts +3 -0
  54. package/dist/esm/dialect/sqlite/sqlite-query-compiler.js +10 -0
  55. package/dist/esm/index.d.ts +2 -0
  56. package/dist/esm/index.js +2 -0
  57. package/dist/esm/operation-node/create-table-node.d.ts +6 -1
  58. package/dist/esm/operation-node/create-table-node.js +16 -0
  59. package/dist/esm/operation-node/delete-query-node.d.ts +3 -0
  60. package/dist/esm/operation-node/delete-query-node.js +6 -0
  61. package/dist/esm/operation-node/explain-node.d.ts +16 -0
  62. package/dist/esm/operation-node/explain-node.js +17 -0
  63. package/dist/esm/operation-node/insert-query-node.d.ts +2 -0
  64. package/dist/esm/operation-node/operation-node-transformer.d.ts +2 -0
  65. package/dist/esm/operation-node/operation-node-transformer.js +14 -0
  66. package/dist/esm/operation-node/operation-node-visitor.d.ts +2 -0
  67. package/dist/esm/operation-node/operation-node-visitor.js +1 -0
  68. package/dist/esm/operation-node/operation-node.d.ts +1 -1
  69. package/dist/esm/operation-node/select-query-node.d.ts +3 -0
  70. package/dist/esm/operation-node/select-query-node.js +6 -0
  71. package/dist/esm/operation-node/update-query-node.d.ts +3 -0
  72. package/dist/esm/operation-node/update-query-node.js +6 -0
  73. package/dist/esm/query-builder/delete-query-builder.d.ts +19 -1
  74. package/dist/esm/query-builder/delete-query-builder.js +24 -0
  75. package/dist/esm/query-builder/function-builder.d.ts +3 -3
  76. package/dist/esm/query-builder/insert-query-builder.d.ts +20 -2
  77. package/dist/esm/query-builder/insert-query-builder.js +26 -0
  78. package/dist/esm/query-builder/select-query-builder.d.ts +38 -1
  79. package/dist/esm/query-builder/select-query-builder.js +45 -2
  80. package/dist/esm/query-builder/update-query-builder.d.ts +20 -1
  81. package/dist/esm/query-builder/update-query-builder.js +25 -0
  82. package/dist/esm/query-compiler/default-query-compiler.d.ts +6 -0
  83. package/dist/esm/query-compiler/default-query-compiler.js +58 -3
  84. package/dist/esm/raw-builder/sql.d.ts +96 -96
  85. package/dist/esm/raw-builder/sql.js +0 -96
  86. package/dist/esm/schema/create-table-builder.d.ts +54 -0
  87. package/dist/esm/schema/create-table-builder.js +64 -0
  88. package/dist/esm/util/explainable.d.ts +5 -0
  89. package/dist/esm/util/explainable.js +2 -0
  90. package/package.json +3 -1
@@ -1,4 +1,4 @@
1
- export declare type OperationNodeKind = 'IdentifierNode' | 'RawNode' | 'SelectQueryNode' | 'SelectionNode' | 'ReferenceNode' | 'ColumnNode' | 'TableNode' | 'AliasNode' | 'FromNode' | 'SelectAllNode' | 'FilterNode' | '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' | 'UnionNode' | 'CreateViewNode' | 'DropViewNode' | 'GeneratedNode' | 'DefaultValueNode' | 'OnNode' | 'ValuesNode' | 'CommonTableExpressionNameNode' | 'SelectModifierNode' | 'CreateTypeNode' | 'DropTypeNode';
1
+ export declare type OperationNodeKind = 'IdentifierNode' | 'RawNode' | 'SelectQueryNode' | 'SelectionNode' | 'ReferenceNode' | 'ColumnNode' | 'TableNode' | 'AliasNode' | 'FromNode' | 'SelectAllNode' | 'FilterNode' | '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' | 'UnionNode' | 'CreateViewNode' | 'DropViewNode' | 'GeneratedNode' | 'DefaultValueNode' | 'OnNode' | 'ValuesNode' | 'CommonTableExpressionNameNode' | 'SelectModifierNode' | 'CreateTypeNode' | 'DropTypeNode' | 'ExplainNode';
2
2
  export interface OperationNode {
3
3
  readonly kind: OperationNodeKind;
4
4
  }
@@ -14,6 +14,7 @@ import { WhereNode } from './where-node.js';
14
14
  import { WithNode } from './with-node.js';
15
15
  import { UnionNode } from './union-node.js';
16
16
  import { SelectModifierNode } from './select-modifier-node.js';
17
+ import { ExplainNode } from './explain-node.js';
17
18
  export interface SelectQueryNode extends OperationNode {
18
19
  readonly kind: 'SelectQueryNode';
19
20
  readonly from: FromNode;
@@ -30,6 +31,7 @@ export interface SelectQueryNode extends OperationNode {
30
31
  readonly with?: WithNode;
31
32
  readonly having?: HavingNode;
32
33
  readonly union?: ReadonlyArray<UnionNode>;
34
+ readonly explain?: ExplainNode;
33
35
  }
34
36
  /**
35
37
  * @internal
@@ -48,4 +50,5 @@ export declare const SelectQueryNode: Readonly<{
48
50
  cloneWithHaving(selectNode: SelectQueryNode, filter: FilterExpressionNode): SelectQueryNode;
49
51
  cloneWithOrHaving(selectNode: SelectQueryNode, filter: FilterExpressionNode): SelectQueryNode;
50
52
  cloneWithUnion(selectNode: SelectQueryNode, union: UnionNode): SelectQueryNode;
53
+ cloneWithExplain(selectNode: SelectQueryNode, explain: ExplainNode): SelectQueryNode;
51
54
  }>;
@@ -102,4 +102,10 @@ export const SelectQueryNode = freeze({
102
102
  : freeze([union]),
103
103
  });
104
104
  },
105
+ cloneWithExplain(selectNode, explain) {
106
+ return freeze({
107
+ ...selectNode,
108
+ explain,
109
+ });
110
+ },
105
111
  });
@@ -8,6 +8,7 @@ import { ValueListNode } from './value-list-node.js';
8
8
  import { WhereNode } from './where-node.js';
9
9
  import { WithNode } from './with-node.js';
10
10
  import { FromNode } from './from-node.js';
11
+ import { ExplainNode } from './explain-node.js';
11
12
  export declare type UpdateValuesNode = ValueListNode | PrimitiveValueListNode;
12
13
  export interface UpdateQueryNode extends OperationNode {
13
14
  readonly kind: 'UpdateQueryNode';
@@ -18,6 +19,7 @@ export interface UpdateQueryNode extends OperationNode {
18
19
  readonly updates?: ReadonlyArray<ColumnUpdateNode>;
19
20
  readonly returning?: ReturningNode;
20
21
  readonly with?: WithNode;
22
+ readonly explain?: ExplainNode;
21
23
  }
22
24
  /**
23
25
  * @internal
@@ -27,4 +29,5 @@ export declare const UpdateQueryNode: Readonly<{
27
29
  create(table: TableExpressionNode, withNode?: WithNode): UpdateQueryNode;
28
30
  cloneWithFromItems(updateQuery: UpdateQueryNode, fromItems: ReadonlyArray<TableExpressionNode>): UpdateQueryNode;
29
31
  cloneWithUpdates(updateQuery: UpdateQueryNode, updates: ReadonlyArray<ColumnUpdateNode>): UpdateQueryNode;
32
+ cloneWithExplain(updateQuery: UpdateQueryNode, explain: ExplainNode): UpdateQueryNode;
30
33
  }>;
@@ -31,4 +31,10 @@ export const UpdateQueryNode = freeze({
31
31
  : updates,
32
32
  });
33
33
  },
34
+ cloneWithExplain(updateQuery, explain) {
35
+ return freeze({
36
+ ...updateQuery,
37
+ explain,
38
+ });
39
+ },
34
40
  });
@@ -20,7 +20,8 @@ import { Selectable } from '../util/column-type.js';
20
20
  import { OrderByDirectionExpression, OrderByExpression } from '../parser/order-by-parser.js';
21
21
  import { AliasedQueryBuilder } from './select-query-builder.js';
22
22
  import { AliasedRawBuilder } from '../raw-builder/raw-builder.js';
23
- export declare class DeleteQueryBuilder<DB, TB extends keyof DB, O> implements WhereInterface<DB, TB>, ReturningInterface<DB, TB, O>, OperationNodeSource, Compilable {
23
+ import { Explainable, ExplainFormat } from '../util/explainable.js';
24
+ export declare class DeleteQueryBuilder<DB, TB extends keyof DB, O> implements WhereInterface<DB, TB>, ReturningInterface<DB, TB, O>, OperationNodeSource, Compilable, Explainable {
24
25
  #private;
25
26
  constructor(props: DeleteQueryBuilderProps);
26
27
  /**
@@ -744,6 +745,23 @@ export declare class DeleteQueryBuilder<DB, TB extends keyof DB, O> implements W
744
745
  * error.
745
746
  */
746
747
  executeTakeFirstOrThrow(errorConstructor?: NoResultErrorConstructor): Promise<O>;
748
+ /**
749
+ * Executes query with `explain` statement before `delete` keyword.
750
+ *
751
+ * ```ts
752
+ * const explained = await db
753
+ * .deleteFrom('person')
754
+ * .where('id', '=', 123)
755
+ * .explain('json')
756
+ * ```
757
+ *
758
+ * The generated SQL (MySQL):
759
+ *
760
+ * ```sql
761
+ * explain format=json delete from `person` where `id` = ?
762
+ * ```
763
+ */
764
+ explain<ER extends Record<string, any> = Record<string, any>>(format?: ExplainFormat, options?: AnyRawBuilder): Promise<ER[]>;
747
765
  }
748
766
  export interface DeleteQueryBuilderProps {
749
767
  readonly queryId: QueryId;
@@ -10,6 +10,7 @@ import { DeleteResult } from './delete-result.js';
10
10
  import { DeleteQueryNode } from '../operation-node/delete-query-node.js';
11
11
  import { LimitNode } from '../operation-node/limit-node.js';
12
12
  import { parseOrderBy, } from '../parser/order-by-parser.js';
13
+ import { ExplainNode } from '../operation-node/explain-node.js';
13
14
  export class DeleteQueryBuilder {
14
15
  #props;
15
16
  constructor(props) {
@@ -293,5 +294,28 @@ export class DeleteQueryBuilder {
293
294
  }
294
295
  return result;
295
296
  }
297
+ /**
298
+ * Executes query with `explain` statement before `delete` keyword.
299
+ *
300
+ * ```ts
301
+ * const explained = await db
302
+ * .deleteFrom('person')
303
+ * .where('id', '=', 123)
304
+ * .explain('json')
305
+ * ```
306
+ *
307
+ * The generated SQL (MySQL):
308
+ *
309
+ * ```sql
310
+ * explain format=json delete from `person` where `id` = ?
311
+ * ```
312
+ */
313
+ async explain(format, options) {
314
+ const builder = new DeleteQueryBuilder({
315
+ ...this.#props,
316
+ queryNode: DeleteQueryNode.cloneWithExplain(this.#props.queryNode, ExplainNode.create(format, options)),
317
+ });
318
+ return await builder.execute();
319
+ }
296
320
  }
297
321
  preventAwait(DeleteQueryBuilder, "don't await DeleteQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`.");
@@ -85,7 +85,7 @@ export declare class FunctionBuilder<DB, TB extends keyof DB> {
85
85
  * .execute()
86
86
  * ```
87
87
  */
88
- avg<O extends number | string, C extends StringReference<DB, TB> = any>(column: C): RawBuilder<O>;
88
+ avg<O extends number | string, C extends StringReference<DB, TB> = StringReference<DB, TB>>(column: C): RawBuilder<O>;
89
89
  /**
90
90
  * Calls the `sum` function for the column given as the argument.
91
91
  *
@@ -107,7 +107,7 @@ export declare class FunctionBuilder<DB, TB extends keyof DB> {
107
107
  * .execute()
108
108
  * ```
109
109
  */
110
- sum<O extends number | string | bigint, C extends StringReference<DB, TB> = any>(column: C): RawBuilder<O>;
110
+ sum<O extends number | string | bigint, C extends StringReference<DB, TB> = StringReference<DB, TB>>(column: C): RawBuilder<O>;
111
111
  /**
112
112
  * Calls the `count` function for the column given as the argument.
113
113
  *
@@ -129,5 +129,5 @@ export declare class FunctionBuilder<DB, TB extends keyof DB> {
129
129
  * .execute()
130
130
  * ```
131
131
  */
132
- count<O extends number | string | bigint, C extends StringReference<DB, TB> = any>(column: C): RawBuilder<O>;
132
+ count<O extends number | string | bigint, C extends StringReference<DB, TB> = StringReference<DB, TB>>(column: C): RawBuilder<O>;
133
133
  }
@@ -3,7 +3,7 @@ import { CompiledQuery } from '../query-compiler/compiled-query.js';
3
3
  import { SelectExpression } from '../parser/select-parser.js';
4
4
  import { InsertObject } from '../parser/insert-values-parser.js';
5
5
  import { InsertQueryNode } from '../operation-node/insert-query-node.js';
6
- import { MergePartial, SingleResultType } from '../util/type-utils.js';
6
+ import { AnyRawBuilder, MergePartial, SingleResultType } from '../util/type-utils.js';
7
7
  import { MutationObject } from '../parser/update-set-parser.js';
8
8
  import { Compilable } from '../util/compilable.js';
9
9
  import { QueryExecutor } from '../query-executor/query-executor.js';
@@ -16,7 +16,8 @@ import { ComplexExpression } from '../parser/complex-expression-parser.js';
16
16
  import { ReturningInterface } from './returning-interface.js';
17
17
  import { OnConflictBuilder, OnConflictDoNothingBuilder, OnConflictUpdateBuilder } from './on-conflict-builder.js';
18
18
  import { Selectable } from '../util/column-type.js';
19
- export declare class InsertQueryBuilder<DB, TB extends keyof DB, O> implements ReturningInterface<DB, TB, O>, OperationNodeSource, Compilable {
19
+ import { Explainable, ExplainFormat } from '../util/explainable.js';
20
+ export declare class InsertQueryBuilder<DB, TB extends keyof DB, O> implements ReturningInterface<DB, TB, O>, OperationNodeSource, Compilable, Explainable {
20
21
  #private;
21
22
  constructor(props: InsertQueryBuilderProps);
22
23
  /**
@@ -541,6 +542,23 @@ export declare class InsertQueryBuilder<DB, TB extends keyof DB, O> implements R
541
542
  * error.
542
543
  */
543
544
  executeTakeFirstOrThrow(errorConstructor?: NoResultErrorConstructor): Promise<O>;
545
+ /**
546
+ * Executes query with `explain` statement before `insert` keyword.
547
+ *
548
+ * ```ts
549
+ * const explained = await db
550
+ * .insertInto('person')
551
+ * .values(values)
552
+ * .explain('json')
553
+ * ```
554
+ *
555
+ * The generated SQL (MySQL):
556
+ *
557
+ * ```sql
558
+ * explain format=json insert into `person` (`id`, `first_name`, `last_name`) values (?, ?, ?) (?, ?, ?)
559
+ * ```
560
+ */
561
+ explain<ER extends Record<string, any> = Record<string, any>>(format?: ExplainFormat, options?: AnyRawBuilder): Promise<ER[]>;
544
562
  }
545
563
  export interface InsertQueryBuilderProps {
546
564
  readonly queryId: QueryId;
@@ -13,6 +13,7 @@ import { parseComplexExpression, } from '../parser/complex-expression-parser.js'
13
13
  import { ColumnNode } from '../operation-node/column-node.js';
14
14
  import { OnConflictBuilder, } from './on-conflict-builder.js';
15
15
  import { OnConflictNode } from '../operation-node/on-conflict-node.js';
16
+ import { ExplainNode } from '../operation-node/explain-node.js';
16
17
  export class InsertQueryBuilder {
17
18
  #props;
18
19
  constructor(props) {
@@ -444,5 +445,30 @@ export class InsertQueryBuilder {
444
445
  }
445
446
  return result;
446
447
  }
448
+ /**
449
+ * Executes query with `explain` statement before `insert` keyword.
450
+ *
451
+ * ```ts
452
+ * const explained = await db
453
+ * .insertInto('person')
454
+ * .values(values)
455
+ * .explain('json')
456
+ * ```
457
+ *
458
+ * The generated SQL (MySQL):
459
+ *
460
+ * ```sql
461
+ * explain format=json insert into `person` (`id`, `first_name`, `last_name`) values (?, ?, ?) (?, ?, ?)
462
+ * ```
463
+ */
464
+ async explain(format, options) {
465
+ const builder = new InsertQueryBuilder({
466
+ ...this.#props,
467
+ queryNode: InsertQueryNode.cloneWith(this.#props.queryNode, {
468
+ explain: ExplainNode.create(format, options),
469
+ }),
470
+ });
471
+ return await builder.execute();
472
+ }
447
473
  }
448
474
  preventAwait(InsertQueryBuilder, "don't await InsertQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`.");
@@ -18,7 +18,8 @@ import { WhereInterface } from './where-interface.js';
18
18
  import { NoResultErrorConstructor } from './no-result-error.js';
19
19
  import { HavingInterface } from './having-interface.js';
20
20
  import { AliasedRawBuilder } from '../raw-builder/raw-builder.js';
21
- export declare class SelectQueryBuilder<DB, TB extends keyof DB, O> implements WhereInterface<DB, TB>, HavingInterface<DB, TB>, OperationNodeSource, Compilable {
21
+ import { Explainable, ExplainFormat } from '../util/explainable.js';
22
+ export declare class SelectQueryBuilder<DB, TB extends keyof DB, O> implements WhereInterface<DB, TB>, HavingInterface<DB, TB>, OperationNodeSource, Compilable, Explainable {
22
23
  #private;
23
24
  constructor(props: SelectQueryBuilderProps);
24
25
  /**
@@ -1370,6 +1371,42 @@ export declare class SelectQueryBuilder<DB, TB extends keyof DB, O> implements W
1370
1371
  * ```
1371
1372
  */
1372
1373
  stream(chunkSize?: number): AsyncIterableIterator<O>;
1374
+ /**
1375
+ * Executes query with `explain` statement before `select` keyword.
1376
+ *
1377
+ * ```ts
1378
+ * const explained = await db
1379
+ * .selectFrom('person')
1380
+ * .where('gender', '=', 'female')
1381
+ * .selectAll()
1382
+ * .explain('json')
1383
+ * ```
1384
+ *
1385
+ * The generated SQL (MySQL):
1386
+ *
1387
+ * ```sql
1388
+ * explain format=json select * from `person` where `gender` = ?
1389
+ * ```
1390
+ *
1391
+ * You can also execute `explain analyze` statements.
1392
+ *
1393
+ * ```ts
1394
+ * import { sql } from 'kysely'
1395
+ *
1396
+ * const explained = await db
1397
+ * .selectFrom('person')
1398
+ * .where('gender', '=', 'female')
1399
+ * .selectAll()
1400
+ * .explain('json', sql`analyze`)
1401
+ * ```
1402
+ *
1403
+ * The generated SQL (PostgreSQL):
1404
+ *
1405
+ * ```sql
1406
+ * explain (analyze, format json) select * from "person" where "gender" = $1
1407
+ * ```
1408
+ */
1409
+ explain<ER extends Record<string, any> = Record<string, any>>(format?: ExplainFormat, options?: AnyRawBuilder): Promise<ER[]>;
1373
1410
  }
1374
1411
  export interface SelectQueryBuilderProps {
1375
1412
  readonly queryId: QueryId;
@@ -15,6 +15,7 @@ import { parseGroupBy } from '../parser/group-by-parser.js';
15
15
  import { parseUnion } from '../parser/union-parser.js';
16
16
  import { NoResultError } from './no-result-error.js';
17
17
  import { IdentifierNode } from '../operation-node/identifier-node.js';
18
+ import { ExplainNode } from '../operation-node/explain-node.js';
18
19
  export class SelectQueryBuilder {
19
20
  #props;
20
21
  constructor(props) {
@@ -627,8 +628,8 @@ export class SelectQueryBuilder {
627
628
  * Also see the {@link executeTakeFirst} and {@link executeTakeFirstOrThrow} methods.
628
629
  */
629
630
  async execute() {
630
- const compildQuery = this.compile();
631
- const result = await this.#props.executor.executeQuery(compildQuery, this.#props.queryId);
631
+ const compiledQuery = this.compile();
632
+ const result = await this.#props.executor.executeQuery(compiledQuery, this.#props.queryId);
632
633
  return result.rows;
633
634
  }
634
635
  /**
@@ -687,6 +688,48 @@ export class SelectQueryBuilder {
687
688
  yield* item.rows;
688
689
  }
689
690
  }
691
+ /**
692
+ * Executes query with `explain` statement before `select` keyword.
693
+ *
694
+ * ```ts
695
+ * const explained = await db
696
+ * .selectFrom('person')
697
+ * .where('gender', '=', 'female')
698
+ * .selectAll()
699
+ * .explain('json')
700
+ * ```
701
+ *
702
+ * The generated SQL (MySQL):
703
+ *
704
+ * ```sql
705
+ * explain format=json select * from `person` where `gender` = ?
706
+ * ```
707
+ *
708
+ * You can also execute `explain analyze` statements.
709
+ *
710
+ * ```ts
711
+ * import { sql } from 'kysely'
712
+ *
713
+ * const explained = await db
714
+ * .selectFrom('person')
715
+ * .where('gender', '=', 'female')
716
+ * .selectAll()
717
+ * .explain('json', sql`analyze`)
718
+ * ```
719
+ *
720
+ * The generated SQL (PostgreSQL):
721
+ *
722
+ * ```sql
723
+ * explain (analyze, format json) select * from "person" where "gender" = $1
724
+ * ```
725
+ */
726
+ async explain(format, options) {
727
+ const builder = new SelectQueryBuilder({
728
+ ...this.#props,
729
+ queryNode: SelectQueryNode.cloneWithExplain(this.#props.queryNode, ExplainNode.create(format, options)),
730
+ });
731
+ return await builder.execute();
732
+ }
690
733
  }
691
734
  preventAwait(SelectQueryBuilder, "don't await SelectQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`.");
692
735
  /**
@@ -20,7 +20,8 @@ import { NoResultErrorConstructor } from './no-result-error.js';
20
20
  import { Selectable } from '../util/column-type.js';
21
21
  import { AliasedQueryBuilder } from './select-query-builder.js';
22
22
  import { AliasedRawBuilder } from '../raw-builder/raw-builder.js';
23
- export declare class UpdateQueryBuilder<DB, UT extends keyof DB, TB extends keyof DB, O> implements WhereInterface<DB, TB>, ReturningInterface<DB, TB, O>, OperationNodeSource, Compilable {
23
+ import { Explainable, ExplainFormat } from '../util/explainable.js';
24
+ export declare class UpdateQueryBuilder<DB, UT extends keyof DB, TB extends keyof DB, O> implements WhereInterface<DB, TB>, ReturningInterface<DB, TB, O>, OperationNodeSource, Compilable, Explainable {
24
25
  #private;
25
26
  constructor(props: UpdateQueryBuilderProps);
26
27
  /**
@@ -809,6 +810,24 @@ export declare class UpdateQueryBuilder<DB, UT extends keyof DB, TB extends keyo
809
810
  * error.
810
811
  */
811
812
  executeTakeFirstOrThrow(errorConstructor?: NoResultErrorConstructor): Promise<O>;
813
+ /**
814
+ * Executes query with `explain` statement before `update` keyword.
815
+ *
816
+ * ```ts
817
+ * const explained = await db
818
+ * .updateTable('person')
819
+ * .set(updates)
820
+ * .where('id', '=', 123)
821
+ * .explain('json')
822
+ * ```
823
+ *
824
+ * The generated SQL (MySQL):
825
+ *
826
+ * ```sql
827
+ * explain format=json update `person` set `first_name` = ?, `last_name` = ? where `id` = ?
828
+ * ```
829
+ */
830
+ explain<ER extends Record<string, any> = Record<string, any>>(format?: ExplainFormat, options?: AnyRawBuilder): Promise<ER[]>;
812
831
  }
813
832
  export interface UpdateQueryBuilderProps {
814
833
  readonly queryId: QueryId;
@@ -10,6 +10,7 @@ import { preventAwait } from '../util/prevent-await.js';
10
10
  import { freeze } from '../util/object-utils.js';
11
11
  import { UpdateResult } from './update-result.js';
12
12
  import { NoResultError } from './no-result-error.js';
13
+ import { ExplainNode } from '../operation-node/explain-node.js';
13
14
  export class UpdateQueryBuilder {
14
15
  #props;
15
16
  constructor(props) {
@@ -330,5 +331,29 @@ export class UpdateQueryBuilder {
330
331
  }
331
332
  return result;
332
333
  }
334
+ /**
335
+ * Executes query with `explain` statement before `update` keyword.
336
+ *
337
+ * ```ts
338
+ * const explained = await db
339
+ * .updateTable('person')
340
+ * .set(updates)
341
+ * .where('id', '=', 123)
342
+ * .explain('json')
343
+ * ```
344
+ *
345
+ * The generated SQL (MySQL):
346
+ *
347
+ * ```sql
348
+ * explain format=json update `person` set `first_name` = ?, `last_name` = ? where `id` = ?
349
+ * ```
350
+ */
351
+ async explain(format, options) {
352
+ const builder = new UpdateQueryBuilder({
353
+ ...this.#props,
354
+ queryNode: UpdateQueryNode.cloneWithExplain(this.#props.queryNode, ExplainNode.create(format, options)),
355
+ });
356
+ return await builder.execute();
357
+ }
333
358
  }
334
359
  preventAwait(UpdateQueryBuilder, "don't await UpdateQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`.");
@@ -71,6 +71,7 @@ import { CommonTableExpressionNameNode } from '../operation-node/common-table-ex
71
71
  import { SelectModifierNode } from '../operation-node/select-modifier-node.js';
72
72
  import { CreateTypeNode } from '../operation-node/create-type-node.js';
73
73
  import { DropTypeNode } from '../operation-node/drop-type-node.js';
74
+ import { ExplainNode } from '../operation-node/explain-node.js';
74
75
  export declare class DefaultQueryCompiler extends OperationNodeVisitor implements QueryCompiler {
75
76
  #private;
76
77
  protected get numParameters(): number;
@@ -149,11 +150,16 @@ export declare class DefaultQueryCompiler extends OperationNodeVisitor implement
149
150
  protected visitSelectModifier(node: SelectModifierNode): void;
150
151
  protected visitCreateType(node: CreateTypeNode): void;
151
152
  protected visitDropType(node: DropTypeNode): void;
153
+ protected visitExplain(node: ExplainNode): void;
152
154
  protected append(str: string): void;
153
155
  protected appendValue(parameter: unknown): void;
154
156
  protected getLeftIdentifierWrapper(): string;
155
157
  protected getRightIdentifierWrapper(): string;
156
158
  protected getCurrentParameterPlaceholder(): string;
159
+ protected getLeftExplainOptionsWrapper(): string;
160
+ protected getExplainOptionAssignment(): string;
161
+ protected getExplainOptionsDelimiter(): string;
162
+ protected getRightExplainOptionsWrapper(): string;
157
163
  protected sanitizeIdentifier(identifier: string): string;
158
164
  protected addParameter(parameter: unknown): void;
159
165
  protected appendImmediateValue(value: unknown): void;
@@ -30,6 +30,10 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
30
30
  !InsertQueryNode.is(this.parentNode) &&
31
31
  !CreateViewNode.is(this.parentNode) &&
32
32
  !UnionNode.is(this.parentNode);
33
+ if (this.parentNode === undefined && node.explain) {
34
+ this.visitNode(node.explain);
35
+ this.append(' ');
36
+ }
33
37
  if (wrapInParens) {
34
38
  this.append('(');
35
39
  }
@@ -125,6 +129,10 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
125
129
  }
126
130
  visitInsertQuery(node) {
127
131
  const isSubQuery = this.nodeStack.find(QueryNode.is) !== node;
132
+ if (!isSubQuery && node.explain) {
133
+ this.visitNode(node.explain);
134
+ this.append(' ');
135
+ }
128
136
  if (isSubQuery) {
129
137
  this.append('(');
130
138
  }
@@ -169,6 +177,10 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
169
177
  }
170
178
  visitDeleteQuery(node) {
171
179
  const isSubQuery = this.nodeStack.find(QueryNode.is) !== node;
180
+ if (!isSubQuery && node.explain) {
181
+ this.visitNode(node.explain);
182
+ this.append(' ');
183
+ }
172
184
  if (isSubQuery) {
173
185
  this.append('(');
174
186
  }
@@ -225,6 +237,9 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
225
237
  this.append(this.getRightIdentifierWrapper());
226
238
  }
227
239
  compileUnwrappedIdentifier(node) {
240
+ if (!isString(node.identifier)) {
241
+ throw new Error('a non-string identifier was passed to compileUnwrappedIdentifier.');
242
+ }
228
243
  this.append(this.sanitizeIdentifier(node.identifier));
229
244
  }
230
245
  visitFilter(node) {
@@ -309,6 +324,10 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
309
324
  }
310
325
  visitCreateTable(node) {
311
326
  this.append('create ');
327
+ if (node.frontModifiers) {
328
+ this.compileList(node.frontModifiers, ' ');
329
+ this.append(' ');
330
+ }
312
331
  if (node.temporary) {
313
332
  this.append('temporary ');
314
333
  }
@@ -324,6 +343,10 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
324
343
  this.append(' on commit ');
325
344
  this.append(node.onCommit);
326
345
  }
346
+ if (node.endModifiers) {
347
+ this.append(' ');
348
+ this.compileList(node.endModifiers, ' ');
349
+ }
327
350
  }
328
351
  visitColumnDefinition(node) {
329
352
  this.visitNode(node.column);
@@ -410,6 +433,10 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
410
433
  }
411
434
  visitUpdateQuery(node) {
412
435
  const isSubQuery = this.nodeStack.find(QueryNode.is) !== node;
436
+ if (!isSubQuery && node.explain) {
437
+ this.visitNode(node.explain);
438
+ this.append(' ');
439
+ }
413
440
  if (isSubQuery) {
414
441
  this.append('(');
415
442
  }
@@ -804,6 +831,25 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
804
831
  }
805
832
  this.visitNode(node.name);
806
833
  }
834
+ visitExplain(node) {
835
+ this.append('explain');
836
+ if (node.options || node.format) {
837
+ this.append(' ');
838
+ this.append(this.getLeftExplainOptionsWrapper());
839
+ if (node.options) {
840
+ this.visitNode(node.options);
841
+ if (node.format) {
842
+ this.append(this.getExplainOptionsDelimiter());
843
+ }
844
+ }
845
+ if (node.format) {
846
+ this.append('format');
847
+ this.append(this.getExplainOptionAssignment());
848
+ this.append(node.format);
849
+ }
850
+ this.append(this.getRightExplainOptionsWrapper());
851
+ }
852
+ }
807
853
  append(str) {
808
854
  this.#sql += str;
809
855
  }
@@ -820,10 +866,19 @@ export class DefaultQueryCompiler extends OperationNodeVisitor {
820
866
  getCurrentParameterPlaceholder() {
821
867
  return '$' + this.numParameters;
822
868
  }
869
+ getLeftExplainOptionsWrapper() {
870
+ return '(';
871
+ }
872
+ getExplainOptionAssignment() {
873
+ return ' ';
874
+ }
875
+ getExplainOptionsDelimiter() {
876
+ return ', ';
877
+ }
878
+ getRightExplainOptionsWrapper() {
879
+ return ')';
880
+ }
823
881
  sanitizeIdentifier(identifier) {
824
- if (!isString(identifier)) {
825
- throw new Error('a non-string identifier was passed to sanitizeIdentifier.');
826
- }
827
882
  const leftWrap = this.getLeftIdentifierWrapper();
828
883
  const rightWrap = this.getRightIdentifierWrapper();
829
884
  let sanitized = '';