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
@@ -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;
@@ -15,6 +15,7 @@ const complex_expression_parser_js_1 = require("../parser/complex-expression-par
15
15
  const column_node_js_1 = require("../operation-node/column-node.js");
16
16
  const on_conflict_builder_js_1 = require("./on-conflict-builder.js");
17
17
  const on_conflict_node_js_1 = require("../operation-node/on-conflict-node.js");
18
+ const explain_node_js_1 = require("../operation-node/explain-node.js");
18
19
  class InsertQueryBuilder {
19
20
  #props;
20
21
  constructor(props) {
@@ -446,6 +447,31 @@ class InsertQueryBuilder {
446
447
  }
447
448
  return result;
448
449
  }
450
+ /**
451
+ * Executes query with `explain` statement before `insert` keyword.
452
+ *
453
+ * ```ts
454
+ * const explained = await db
455
+ * .insertInto('person')
456
+ * .values(values)
457
+ * .explain('json')
458
+ * ```
459
+ *
460
+ * The generated SQL (MySQL):
461
+ *
462
+ * ```sql
463
+ * explain format=json insert into `person` (`id`, `first_name`, `last_name`) values (?, ?, ?) (?, ?, ?)
464
+ * ```
465
+ */
466
+ async explain(format, options) {
467
+ const builder = new InsertQueryBuilder({
468
+ ...this.#props,
469
+ queryNode: insert_query_node_js_1.InsertQueryNode.cloneWith(this.#props.queryNode, {
470
+ explain: explain_node_js_1.ExplainNode.create(format, options),
471
+ }),
472
+ });
473
+ return await builder.execute();
474
+ }
449
475
  }
450
476
  exports.InsertQueryBuilder = InsertQueryBuilder;
451
477
  (0, prevent_await_js_1.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;
@@ -17,6 +17,7 @@ const group_by_parser_js_1 = require("../parser/group-by-parser.js");
17
17
  const union_parser_js_1 = require("../parser/union-parser.js");
18
18
  const no_result_error_js_1 = require("./no-result-error.js");
19
19
  const identifier_node_js_1 = require("../operation-node/identifier-node.js");
20
+ const explain_node_js_1 = require("../operation-node/explain-node.js");
20
21
  class SelectQueryBuilder {
21
22
  #props;
22
23
  constructor(props) {
@@ -629,8 +630,8 @@ class SelectQueryBuilder {
629
630
  * Also see the {@link executeTakeFirst} and {@link executeTakeFirstOrThrow} methods.
630
631
  */
631
632
  async execute() {
632
- const compildQuery = this.compile();
633
- const result = await this.#props.executor.executeQuery(compildQuery, this.#props.queryId);
633
+ const compiledQuery = this.compile();
634
+ const result = await this.#props.executor.executeQuery(compiledQuery, this.#props.queryId);
634
635
  return result.rows;
635
636
  }
636
637
  /**
@@ -689,6 +690,48 @@ class SelectQueryBuilder {
689
690
  yield* item.rows;
690
691
  }
691
692
  }
693
+ /**
694
+ * Executes query with `explain` statement before `select` keyword.
695
+ *
696
+ * ```ts
697
+ * const explained = await db
698
+ * .selectFrom('person')
699
+ * .where('gender', '=', 'female')
700
+ * .selectAll()
701
+ * .explain('json')
702
+ * ```
703
+ *
704
+ * The generated SQL (MySQL):
705
+ *
706
+ * ```sql
707
+ * explain format=json select * from `person` where `gender` = ?
708
+ * ```
709
+ *
710
+ * You can also execute `explain analyze` statements.
711
+ *
712
+ * ```ts
713
+ * import { sql } from 'kysely'
714
+ *
715
+ * const explained = await db
716
+ * .selectFrom('person')
717
+ * .where('gender', '=', 'female')
718
+ * .selectAll()
719
+ * .explain('json', sql`analyze`)
720
+ * ```
721
+ *
722
+ * The generated SQL (PostgreSQL):
723
+ *
724
+ * ```sql
725
+ * explain (analyze, format json) select * from "person" where "gender" = $1
726
+ * ```
727
+ */
728
+ async explain(format, options) {
729
+ const builder = new SelectQueryBuilder({
730
+ ...this.#props,
731
+ queryNode: select_query_node_js_1.SelectQueryNode.cloneWithExplain(this.#props.queryNode, explain_node_js_1.ExplainNode.create(format, options)),
732
+ });
733
+ return await builder.execute();
734
+ }
692
735
  }
693
736
  exports.SelectQueryBuilder = SelectQueryBuilder;
694
737
  (0, prevent_await_js_1.preventAwait)(SelectQueryBuilder, "don't await SelectQueryBuilder instances directly. To execute the query you need to call `execute` or `executeTakeFirst`.");
@@ -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;
@@ -12,6 +12,7 @@ const prevent_await_js_1 = require("../util/prevent-await.js");
12
12
  const object_utils_js_1 = require("../util/object-utils.js");
13
13
  const update_result_js_1 = require("./update-result.js");
14
14
  const no_result_error_js_1 = require("./no-result-error.js");
15
+ const explain_node_js_1 = require("../operation-node/explain-node.js");
15
16
  class UpdateQueryBuilder {
16
17
  #props;
17
18
  constructor(props) {
@@ -332,6 +333,30 @@ class UpdateQueryBuilder {
332
333
  }
333
334
  return result;
334
335
  }
336
+ /**
337
+ * Executes query with `explain` statement before `update` keyword.
338
+ *
339
+ * ```ts
340
+ * const explained = await db
341
+ * .updateTable('person')
342
+ * .set(updates)
343
+ * .where('id', '=', 123)
344
+ * .explain('json')
345
+ * ```
346
+ *
347
+ * The generated SQL (MySQL):
348
+ *
349
+ * ```sql
350
+ * explain format=json update `person` set `first_name` = ?, `last_name` = ? where `id` = ?
351
+ * ```
352
+ */
353
+ async explain(format, options) {
354
+ const builder = new UpdateQueryBuilder({
355
+ ...this.#props,
356
+ queryNode: update_query_node_js_1.UpdateQueryNode.cloneWithExplain(this.#props.queryNode, explain_node_js_1.ExplainNode.create(format, options)),
357
+ });
358
+ return await builder.execute();
359
+ }
335
360
  }
336
361
  exports.UpdateQueryBuilder = UpdateQueryBuilder;
337
362
  (0, prevent_await_js_1.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;
@@ -32,6 +32,10 @@ class DefaultQueryCompiler extends operation_node_visitor_js_1.OperationNodeVisi
32
32
  !insert_query_node_js_1.InsertQueryNode.is(this.parentNode) &&
33
33
  !create_view_node_js_1.CreateViewNode.is(this.parentNode) &&
34
34
  !union_node_js_1.UnionNode.is(this.parentNode);
35
+ if (this.parentNode === undefined && node.explain) {
36
+ this.visitNode(node.explain);
37
+ this.append(' ');
38
+ }
35
39
  if (wrapInParens) {
36
40
  this.append('(');
37
41
  }
@@ -127,6 +131,10 @@ class DefaultQueryCompiler extends operation_node_visitor_js_1.OperationNodeVisi
127
131
  }
128
132
  visitInsertQuery(node) {
129
133
  const isSubQuery = this.nodeStack.find(query_node_js_1.QueryNode.is) !== node;
134
+ if (!isSubQuery && node.explain) {
135
+ this.visitNode(node.explain);
136
+ this.append(' ');
137
+ }
130
138
  if (isSubQuery) {
131
139
  this.append('(');
132
140
  }
@@ -171,6 +179,10 @@ class DefaultQueryCompiler extends operation_node_visitor_js_1.OperationNodeVisi
171
179
  }
172
180
  visitDeleteQuery(node) {
173
181
  const isSubQuery = this.nodeStack.find(query_node_js_1.QueryNode.is) !== node;
182
+ if (!isSubQuery && node.explain) {
183
+ this.visitNode(node.explain);
184
+ this.append(' ');
185
+ }
174
186
  if (isSubQuery) {
175
187
  this.append('(');
176
188
  }
@@ -227,6 +239,9 @@ class DefaultQueryCompiler extends operation_node_visitor_js_1.OperationNodeVisi
227
239
  this.append(this.getRightIdentifierWrapper());
228
240
  }
229
241
  compileUnwrappedIdentifier(node) {
242
+ if (!(0, object_utils_js_1.isString)(node.identifier)) {
243
+ throw new Error('a non-string identifier was passed to compileUnwrappedIdentifier.');
244
+ }
230
245
  this.append(this.sanitizeIdentifier(node.identifier));
231
246
  }
232
247
  visitFilter(node) {
@@ -311,6 +326,10 @@ class DefaultQueryCompiler extends operation_node_visitor_js_1.OperationNodeVisi
311
326
  }
312
327
  visitCreateTable(node) {
313
328
  this.append('create ');
329
+ if (node.frontModifiers) {
330
+ this.compileList(node.frontModifiers, ' ');
331
+ this.append(' ');
332
+ }
314
333
  if (node.temporary) {
315
334
  this.append('temporary ');
316
335
  }
@@ -326,6 +345,10 @@ class DefaultQueryCompiler extends operation_node_visitor_js_1.OperationNodeVisi
326
345
  this.append(' on commit ');
327
346
  this.append(node.onCommit);
328
347
  }
348
+ if (node.endModifiers) {
349
+ this.append(' ');
350
+ this.compileList(node.endModifiers, ' ');
351
+ }
329
352
  }
330
353
  visitColumnDefinition(node) {
331
354
  this.visitNode(node.column);
@@ -412,6 +435,10 @@ class DefaultQueryCompiler extends operation_node_visitor_js_1.OperationNodeVisi
412
435
  }
413
436
  visitUpdateQuery(node) {
414
437
  const isSubQuery = this.nodeStack.find(query_node_js_1.QueryNode.is) !== node;
438
+ if (!isSubQuery && node.explain) {
439
+ this.visitNode(node.explain);
440
+ this.append(' ');
441
+ }
415
442
  if (isSubQuery) {
416
443
  this.append('(');
417
444
  }
@@ -806,6 +833,25 @@ class DefaultQueryCompiler extends operation_node_visitor_js_1.OperationNodeVisi
806
833
  }
807
834
  this.visitNode(node.name);
808
835
  }
836
+ visitExplain(node) {
837
+ this.append('explain');
838
+ if (node.options || node.format) {
839
+ this.append(' ');
840
+ this.append(this.getLeftExplainOptionsWrapper());
841
+ if (node.options) {
842
+ this.visitNode(node.options);
843
+ if (node.format) {
844
+ this.append(this.getExplainOptionsDelimiter());
845
+ }
846
+ }
847
+ if (node.format) {
848
+ this.append('format');
849
+ this.append(this.getExplainOptionAssignment());
850
+ this.append(node.format);
851
+ }
852
+ this.append(this.getRightExplainOptionsWrapper());
853
+ }
854
+ }
809
855
  append(str) {
810
856
  this.#sql += str;
811
857
  }
@@ -822,10 +868,19 @@ class DefaultQueryCompiler extends operation_node_visitor_js_1.OperationNodeVisi
822
868
  getCurrentParameterPlaceholder() {
823
869
  return '$' + this.numParameters;
824
870
  }
871
+ getLeftExplainOptionsWrapper() {
872
+ return '(';
873
+ }
874
+ getExplainOptionAssignment() {
875
+ return ' ';
876
+ }
877
+ getExplainOptionsDelimiter() {
878
+ return ', ';
879
+ }
880
+ getRightExplainOptionsWrapper() {
881
+ return ')';
882
+ }
825
883
  sanitizeIdentifier(identifier) {
826
- if (!(0, object_utils_js_1.isString)(identifier)) {
827
- throw new Error('a non-string identifier was passed to sanitizeIdentifier.');
828
- }
829
884
  const leftWrap = this.getLeftIdentifierWrapper();
830
885
  const rightWrap = this.getRightIdentifierWrapper();
831
886
  let sanitized = '';
@@ -1,5 +1,101 @@
1
1
  import { RawBuilder } from './raw-builder.js';
2
2
  export interface Sql {
3
+ /**
4
+ * Template tag for creating raw SQL snippets and queries.
5
+ *
6
+ * ```ts
7
+ * import { sql } from 'kysely'
8
+ *
9
+ * const id = 123
10
+ *
11
+ * const snippet = sql<Person[]>`select * from person where id = ${id}`
12
+ * ```
13
+ *
14
+ * Substitutions (the things inside `${}`) are automatically passed to the database
15
+ * as parameters and are NOT interpolated to the SQL string. There's no need to worry
16
+ * about SQL injection vulnerabilities.
17
+ *
18
+ * If you need your substitutions to be interpreted as identifiers, value literals or
19
+ * lists of things, see the {@link Sql.ref}, {@link Sql.table}, {@link Sql.id},
20
+ * {@link Sql.literal}, {@link Sql.raw} and {@link Sql.join} functions.
21
+ *
22
+ * You can pass sql snippets returned by the `sql` tag pretty much anywhere. Whenever
23
+ * something can't be done using the Kysely API, you should be able to drop down to
24
+ * raw SQL using the `sql` tag. Here's an example query that uses raw sql in a bunch
25
+ * of methods:
26
+ *
27
+ * ```ts
28
+ * const persons = await db
29
+ * .selectFrom('person')
30
+ * .select(
31
+ * // If you use `sql` in a select statement, remember to call the `as`
32
+ * // method to give it an alias. Otherwise Kysely is not able to add
33
+ * // the column to the result type.
34
+ * sql<string>`concat(first_name, ' ', last_name)`.as('full_name')
35
+ * )
36
+ * .where(sql`birthdate between ${date1} and ${date2}`)
37
+ * // Here we assume we have list of nicknames for the person
38
+ * // (a list of strings) and we use the PostgreSQL `@>` operator
39
+ * // to test if all of them are valid nicknames for the user.
40
+ * .where('nicknames', '@>', sql`ARRAY[${sql.join(nicknames)}]`)
41
+ * .orderBy(sql`concat(first_name, ' ', last_name)`)
42
+ * .execute()
43
+ * ```
44
+ *
45
+ * The generated SQL (PostgreSQL):
46
+ *
47
+ * ```sql
48
+ * select concat(first_name, ' ', last_name) as "full_name"
49
+ * from "person"
50
+ * where birthdate between $1 and $2
51
+ * and "nicknames" @> ARRAY[$3, $4, $5, $6, $7, $8, $9, $10]
52
+ * order by concat(first_name, ' ', last_name)
53
+ * ```
54
+ *
55
+ * SQL snippets can be executed by calling the `execute` method and passing a `Kysely`
56
+ * instance as the only argument:
57
+ *
58
+ * ```ts
59
+ * const result = await sql<Person[]>`select * from person`.execute(db)
60
+ * ```
61
+ *
62
+ * You can merge other `sql` expressions and queries using substitutions:
63
+ *
64
+ * ```ts
65
+ * const petName = db.selectFrom('pet').select('name').limit(1)
66
+ * const fullName = sql`concat(first_name, ' ', last_name)`
67
+ *
68
+ * sql`
69
+ * select ${fullName} as full_name, ${petName} as pet_name
70
+ * from person
71
+ * `
72
+ * ```
73
+ *
74
+ * Substitutions also handle {@link ExpressionBuilder.ref},
75
+ * {@link DynamicModule.ref} and pretty much anything else you
76
+ * throw at it. Here's an example of calling a function in a
77
+ * type-safe way:
78
+ *
79
+ * ```ts
80
+ * db.selectFrom('person')
81
+ * .select([
82
+ * 'first_name',
83
+ * 'last_name',
84
+ * (eb) => {
85
+ * // The `eb.ref` method is type-safe and only accepts
86
+ * // column references that are possible.
87
+ * const firstName = eb.ref('first_name')
88
+ * const lastName = eb.ref('last_name')
89
+ *
90
+ * const fullName = sql<string>`concat(${firstName}, ' ', ${lastName})`
91
+ * return fullName.as('full_name')
92
+ * }
93
+ * ])
94
+ * ```
95
+ *
96
+ * don't know if that amount of ceremony is worth the small increase in
97
+ * type-safety though... But it's possible.
98
+ */
3
99
  <T = unknown>(sqlFragments: TemplateStringsArray, ...parameters: unknown[]): RawBuilder<T>;
4
100
  /**
5
101
  * This can be used to add runtime column references to SQL snippets.
@@ -232,100 +328,4 @@ export interface Sql {
232
328
  */
233
329
  join(array: unknown[], separator?: RawBuilder<any>): RawBuilder<unknown>;
234
330
  }
235
- /**
236
- * Template tag for creating raw SQL snippets and queries.
237
- *
238
- * ```ts
239
- * import { sql } from 'kysely'
240
- *
241
- * const id = 123
242
- *
243
- * const snippet = sql<Person[]>`select * from person where id = ${id}`
244
- * ```
245
- *
246
- * Substitutions (the things inside `${}`) are automatically passed to the database
247
- * as parameters and are NOT interpolated to the SQL string. There's no need to worry
248
- * about SQL injection vulnerabilities.
249
- *
250
- * If you need your substitutions to be interpreted as identifiers, value literals or
251
- * lists of things, see the {@link Sql.ref}, {@link Sql.table}, {@link Sql.id},
252
- * {@link Sql.literal}, {@link Sql.raw} and {@link Sql.join} functions.
253
- *
254
- * You can pass sql snippets returned by the `sql` tag pretty much anywhere. Whenever
255
- * something can't be done using the Kysely API, you should be able to drop down to
256
- * raw SQL using the `sql` tag. Here's an example query that uses raw sql in a bunch
257
- * of methods:
258
- *
259
- * ```ts
260
- * const persons = await db
261
- * .selectFrom('person')
262
- * .select(
263
- * // If you use `sql` in a select statement, remember to call the `as`
264
- * // method to give it an alias. Otherwise Kysely is not able to add
265
- * // the column to the result type.
266
- * sql<string>`concat(first_name, ' ', last_name)`.as('full_name')
267
- * )
268
- * .where(sql`birthdate between ${date1} and ${date2}`)
269
- * // Here we assume we have list of nicknames for the person
270
- * // (a list of strings) and we use the PostgreSQL `@>` operator
271
- * // to test if all of them are valid nicknames for the user.
272
- * .where('nicknames', '@>', sql`ARRAY[${sql.join(nicknames)}]`)
273
- * .orderBy(sql`concat(first_name, ' ', last_name)`)
274
- * .execute()
275
- * ```
276
- *
277
- * The generated SQL (PostgreSQL):
278
- *
279
- * ```sql
280
- * select concat(first_name, ' ', last_name) as "full_name"
281
- * from "person"
282
- * where birthdate between $1 and $2
283
- * and "nicknames" @> ARRAY[$3, $4, $5, $6, $7, $8, $9, $10]
284
- * order by concat(first_name, ' ', last_name)
285
- * ```
286
- *
287
- * SQL snippets can be executed by calling the `execute` method and passing a `Kysely`
288
- * instance as the only argument:
289
- *
290
- * ```ts
291
- * const result = await sql<Person[]>`select * from person`.execute(db)
292
- * ```
293
- *
294
- * You can merge other `sql` expressions and queries using substitutions:
295
- *
296
- * ```ts
297
- * const petName = db.selectFrom('pet').select('name').limit(1)
298
- * const fullName = sql`concat(first_name, ' ', last_name)`
299
- *
300
- * sql`
301
- * select ${fullName} as full_name, ${petName} as pet_name
302
- * from person
303
- * `
304
- * ```
305
- *
306
- * Substitutions also handle {@link ExpressionBuilder.ref},
307
- * {@link DynamicModule.ref} and pretty much anything else you
308
- * throw at it. Here's an example of calling a function in a
309
- * type-safe way:
310
- *
311
- * ```ts
312
- * db.selectFrom('person')
313
- * .select([
314
- * 'first_name',
315
- * 'last_name',
316
- * (eb) => {
317
- * // The `eb.ref` method is type-safe and only accepts
318
- * // column references that are possible.
319
- * const firstName = eb.ref('first_name')
320
- * const lastName = eb.ref('last_name')
321
- *
322
- * const fullName = sql<string>`concat(${firstName}, ' ', ${lastName})`
323
- * return fullName.as('full_name')
324
- * }
325
- * ])
326
- * ```
327
- *
328
- * don't know if that amount of ceremony is worth the small increase in
329
- * type-safety though... But it's possible.
330
- */
331
331
  export declare const sql: Sql;