kysely 0.23.3 → 0.23.5

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 (118) hide show
  1. package/README.md +25 -25
  2. package/dist/cjs/dialect/database-introspector.d.ts +4 -2
  3. package/dist/cjs/dialect/dialect-adapter-base.d.ts +32 -6
  4. package/dist/cjs/dialect/dialect-adapter.d.ts +50 -8
  5. package/dist/cjs/dialect/mysql/mysql-adapter.d.ts +32 -6
  6. package/dist/cjs/dialect/mysql/mysql-introspector.d.ts +1 -1
  7. package/dist/cjs/dialect/mysql/mysql-introspector.js +21 -15
  8. package/dist/cjs/dialect/postgres/postgres-adapter.d.ts +32 -6
  9. package/dist/cjs/dialect/postgres/postgres-introspector.d.ts +1 -1
  10. package/dist/cjs/dialect/postgres/postgres-introspector.js +5 -3
  11. package/dist/cjs/dialect/sqlite/sqlite-adapter.d.ts +32 -6
  12. package/dist/cjs/dialect/sqlite/sqlite-introspector.d.ts +1 -1
  13. package/dist/cjs/dialect/sqlite/sqlite-introspector.js +8 -7
  14. package/dist/cjs/index.d.ts +1 -0
  15. package/dist/cjs/index.js +1 -0
  16. package/dist/cjs/migration/migrator.d.ts +8 -3
  17. package/dist/cjs/migration/migrator.js +15 -5
  18. package/dist/cjs/operation-node/aggregate-function-node.d.ts +3 -2
  19. package/dist/cjs/operation-node/aggregate-function-node.js +2 -2
  20. package/dist/cjs/operation-node/create-index-node.d.ts +1 -0
  21. package/dist/cjs/operation-node/delete-query-node.d.ts +4 -1
  22. package/dist/cjs/operation-node/delete-query-node.js +11 -2
  23. package/dist/cjs/operation-node/operation-node-transformer.d.ts +2 -0
  24. package/dist/cjs/operation-node/operation-node-transformer.js +10 -1
  25. package/dist/cjs/operation-node/operation-node-visitor.d.ts +2 -0
  26. package/dist/cjs/operation-node/operation-node-visitor.js +1 -0
  27. package/dist/cjs/operation-node/operation-node.d.ts +1 -1
  28. package/dist/cjs/operation-node/operator-node.d.ts +1 -1
  29. package/dist/cjs/operation-node/operator-node.js +1 -0
  30. package/dist/cjs/operation-node/using-node.d.ts +13 -0
  31. package/dist/cjs/operation-node/using-node.js +24 -0
  32. package/dist/cjs/parser/expression-parser.js +1 -1
  33. package/dist/cjs/parser/table-parser.d.ts +1 -0
  34. package/dist/cjs/parser/update-set-parser.d.ts +1 -1
  35. package/dist/cjs/plugin/camel-case/camel-case-plugin.d.ts +7 -0
  36. package/dist/cjs/plugin/camel-case/camel-case-plugin.js +10 -4
  37. package/dist/cjs/query-builder/delete-query-builder.d.ts +103 -11
  38. package/dist/cjs/query-builder/delete-query-builder.js +40 -9
  39. package/dist/cjs/query-builder/function-module.d.ts +273 -39
  40. package/dist/cjs/query-builder/function-module.js +156 -34
  41. package/dist/cjs/query-builder/insert-query-builder.d.ts +25 -10
  42. package/dist/cjs/query-builder/insert-query-builder.js +32 -9
  43. package/dist/cjs/query-builder/select-query-builder.d.ts +51 -34
  44. package/dist/cjs/query-builder/select-query-builder.js +53 -29
  45. package/dist/cjs/query-builder/update-query-builder.d.ts +26 -10
  46. package/dist/cjs/query-builder/update-query-builder.js +33 -9
  47. package/dist/cjs/query-compiler/default-query-compiler.d.ts +2 -0
  48. package/dist/cjs/query-compiler/default-query-compiler.js +12 -1
  49. package/dist/cjs/query-creator.d.ts +29 -0
  50. package/dist/cjs/query-creator.js +2 -21
  51. package/dist/cjs/raw-builder/raw-builder.d.ts +4 -0
  52. package/dist/cjs/raw-builder/raw-builder.js +8 -2
  53. package/dist/cjs/schema/alter-table-builder.d.ts +5 -1
  54. package/dist/cjs/schema/alter-table-builder.js +8 -2
  55. package/dist/cjs/schema/create-index-builder.d.ts +6 -0
  56. package/dist/cjs/schema/create-index-builder.js +13 -0
  57. package/dist/cjs/schema/create-table-builder.d.ts +6 -2
  58. package/dist/cjs/schema/create-table-builder.js +9 -3
  59. package/dist/cjs/util/type-utils.d.ts +20 -1
  60. package/dist/esm/dialect/database-introspector.d.ts +4 -2
  61. package/dist/esm/dialect/dialect-adapter-base.d.ts +32 -6
  62. package/dist/esm/dialect/dialect-adapter.d.ts +50 -8
  63. package/dist/esm/dialect/mysql/mysql-adapter.d.ts +32 -6
  64. package/dist/esm/dialect/mysql/mysql-introspector.d.ts +1 -1
  65. package/dist/esm/dialect/mysql/mysql-introspector.js +21 -15
  66. package/dist/esm/dialect/postgres/postgres-adapter.d.ts +32 -6
  67. package/dist/esm/dialect/postgres/postgres-introspector.d.ts +1 -1
  68. package/dist/esm/dialect/postgres/postgres-introspector.js +5 -3
  69. package/dist/esm/dialect/sqlite/sqlite-adapter.d.ts +32 -6
  70. package/dist/esm/dialect/sqlite/sqlite-introspector.d.ts +1 -1
  71. package/dist/esm/dialect/sqlite/sqlite-introspector.js +8 -7
  72. package/dist/esm/index.d.ts +1 -0
  73. package/dist/esm/index.js +1 -0
  74. package/dist/esm/migration/migrator.d.ts +8 -3
  75. package/dist/esm/migration/migrator.js +15 -5
  76. package/dist/esm/operation-node/aggregate-function-node.d.ts +3 -2
  77. package/dist/esm/operation-node/aggregate-function-node.js +2 -2
  78. package/dist/esm/operation-node/create-index-node.d.ts +1 -0
  79. package/dist/esm/operation-node/delete-query-node.d.ts +4 -1
  80. package/dist/esm/operation-node/delete-query-node.js +11 -2
  81. package/dist/esm/operation-node/operation-node-transformer.d.ts +2 -0
  82. package/dist/esm/operation-node/operation-node-transformer.js +10 -1
  83. package/dist/esm/operation-node/operation-node-visitor.d.ts +2 -0
  84. package/dist/esm/operation-node/operation-node-visitor.js +1 -0
  85. package/dist/esm/operation-node/operation-node.d.ts +1 -1
  86. package/dist/esm/operation-node/operator-node.d.ts +1 -1
  87. package/dist/esm/operation-node/operator-node.js +1 -0
  88. package/dist/esm/operation-node/using-node.d.ts +13 -0
  89. package/dist/esm/operation-node/using-node.js +22 -0
  90. package/dist/esm/parser/expression-parser.js +2 -2
  91. package/dist/esm/parser/table-parser.d.ts +1 -0
  92. package/dist/esm/parser/update-set-parser.d.ts +1 -1
  93. package/dist/esm/plugin/camel-case/camel-case-plugin.d.ts +7 -0
  94. package/dist/esm/plugin/camel-case/camel-case-plugin.js +10 -4
  95. package/dist/esm/query-builder/delete-query-builder.d.ts +103 -11
  96. package/dist/esm/query-builder/delete-query-builder.js +40 -9
  97. package/dist/esm/query-builder/function-module.d.ts +273 -39
  98. package/dist/esm/query-builder/function-module.js +156 -34
  99. package/dist/esm/query-builder/insert-query-builder.d.ts +25 -10
  100. package/dist/esm/query-builder/insert-query-builder.js +33 -10
  101. package/dist/esm/query-builder/select-query-builder.d.ts +51 -34
  102. package/dist/esm/query-builder/select-query-builder.js +53 -29
  103. package/dist/esm/query-builder/update-query-builder.d.ts +26 -10
  104. package/dist/esm/query-builder/update-query-builder.js +33 -9
  105. package/dist/esm/query-compiler/default-query-compiler.d.ts +2 -0
  106. package/dist/esm/query-compiler/default-query-compiler.js +12 -1
  107. package/dist/esm/query-creator.d.ts +29 -0
  108. package/dist/esm/query-creator.js +2 -21
  109. package/dist/esm/raw-builder/raw-builder.d.ts +4 -0
  110. package/dist/esm/raw-builder/raw-builder.js +8 -2
  111. package/dist/esm/schema/alter-table-builder.d.ts +5 -1
  112. package/dist/esm/schema/alter-table-builder.js +8 -2
  113. package/dist/esm/schema/create-index-builder.d.ts +6 -0
  114. package/dist/esm/schema/create-index-builder.js +13 -0
  115. package/dist/esm/schema/create-table-builder.d.ts +6 -2
  116. package/dist/esm/schema/create-table-builder.js +9 -3
  117. package/dist/esm/util/type-utils.d.ts +20 -1
  118. package/package.json +1 -1
package/README.md CHANGED
@@ -78,6 +78,8 @@ for [3rd party dialects](https://koskimas.github.io/kysely/interfaces/Dialect.ht
78
78
  - [SingleStore Data API](https://github.com/igalklebanov/kysely-singlestore)
79
79
  - [D1](https://github.com/aidenwallis/kysely-d1)
80
80
  - [SurrealDB](https://github.com/igalklebanov/kysely-surrealdb)
81
+ - [sqld](https://github.com/libsql/kysely-libsql)
82
+ - [Neon](https://github.com/seveibar/kysely-neon)
81
83
 
82
84
  # Minimal example
83
85
 
@@ -183,7 +185,7 @@ type UpdateablePerson = Updateable<PersonTable>
183
185
 
184
186
  # Playground
185
187
 
186
- [@wirekang](https://github.com/wirekang) has created a [playground for Kysely](https://wirekang.github.io/kysely-playground/#eyJkaWFsZWN0IjoibXlzcWwiLCJ0cyI6ImludGVyZmFjZSBEQiB7XG4gIHVzZXI6IFVzZXJUYWJsZVxufVxuXG5pbnRlcmZhY2UgVXNlclRhYmxlIHtcbiAgaWQ6IEdlbmVyYXRlZDxzdHJpbmc+XG4gIGZpcnN0X25hbWU6IHN0cmluZyB8IG51bGxcbiAgbGFzdF9uYW1lOiBzdHJpbmcgfCBudWxsXG4gIGNyZWF0ZWRfYXQ6IEdlbmVyYXRlZDxEYXRlPlxufVxuXG5yZXN1bHQgPSBreXNlbHlcbiAgLnNlbGVjdEZyb20oXCJ1c2VyXCIpXG4gIC5zZWxlY3RBbGwoKVxuICAub3JkZXJCeShcImNyZWF0ZWRfYXRcIikifQ==). You can use to quickly test stuff out and for creating code examples for your issues, PRs and discord messages.
188
+ [@wirekang](https://github.com/wirekang) has created a [playground for Kysely](https://wirekang.github.io/kysely-playground/?p=f&i=-NLp3n_P5fyeQKMQda8n). You can use to quickly test stuff out and for creating code examples for your issues, PRs and discord messages.
187
189
 
188
190
  # Generating types
189
191
 
@@ -207,37 +209,34 @@ among other places.
207
209
  import { Pool } from 'pg'
208
210
  // or `import * as Cursor from 'pg-cursor'` depending on your tsconfig
209
211
  import Cursor from 'pg-cursor'
210
- import {
211
- Kysely,
212
- PostgresDialect,
213
- } from 'kysely'
212
+ import { Kysely, PostgresDialect } from 'kysely'
214
213
 
215
214
  const db = new Kysely<Database>({
216
- // PostgresDialect requires the Cursor dependency
217
- dialect: new PostgresDialect({
218
- pool: new Pool({
219
- host: 'localhost',
220
- database: 'kysely_test'
221
- }),
222
- cursor: Cursor
215
+ // PostgresDialect requires the Cursor dependency
216
+ dialect: new PostgresDialect({
217
+ pool: new Pool({
218
+ host: 'localhost',
219
+ database: 'kysely_test'
223
220
  }),
224
-
225
- // MysqlDialect doesn't require any special configuration
221
+ cursor: Cursor
222
+ }),
223
+ // MysqlDialect doesn't require any special configuration
226
224
  })
227
225
 
228
226
  async function demo() {
229
- for await (const male of db.selectFrom("person")
230
- .selectAll()
231
- .where("person.gender", "=", "male")
232
- .stream()) {
233
- console.log(`Hello mr. ${male.first_name}!`)
234
-
235
- if (male.first_name === "John") {
236
- // After this line the db connection is released and no more
237
- // rows are streamed from the database to the client
238
- break;
239
- }
227
+ for await (const adult of db.selectFrom('person')
228
+ .selectAll()
229
+ .where('age', '>', 18)
230
+ .stream()
231
+ ) {
232
+ console.log(`Hello ${adult.first_name}!`)
233
+
234
+ if (adult.first_name === 'John') {
235
+ // After this line the db connection is released and no more
236
+ // rows are streamed from the database to the client
237
+ break;
240
238
  }
239
+ }
241
240
  }
242
241
  ```
243
242
 
@@ -268,6 +267,7 @@ or "recipes" for common use cases.
268
267
  * [Extending kysely](https://github.com/koskimas/kysely/tree/master/recipes/extending-kysely.md)
269
268
  * [Raw SQL](https://github.com/koskimas/kysely/tree/master/recipes/raw-sql.md)
270
269
  * [Schemas](https://github.com/koskimas/kysely/tree/master/recipes/schemas.md)
270
+ * [Dealing with the `Type instantiation is excessively deep and possibly infinite` error](https://github.com/koskimas/kysely/tree/master/recipes/excessively-deep-types.md)
271
271
 
272
272
  # Migrations
273
273
 
@@ -7,7 +7,7 @@ export interface DatabaseIntrospector {
7
7
  */
8
8
  getSchemas(): Promise<SchemaMetadata[]>;
9
9
  /**
10
- * Get table metadata.
10
+ * Get tables and views metadata.
11
11
  */
12
12
  getTables(options?: DatabaseMetadataOptions): Promise<TableMetadata[]>;
13
13
  /**
@@ -29,12 +29,14 @@ export interface SchemaMetadata {
29
29
  }
30
30
  export interface DatabaseMetadata {
31
31
  /**
32
- * The tables found in the database.
32
+ * The tables and views found in the database.
33
+ * * The propery isView can be used to tell them apart.
33
34
  */
34
35
  readonly tables: TableMetadata[];
35
36
  }
36
37
  export interface TableMetadata {
37
38
  readonly name: string;
39
+ readonly isView: boolean;
38
40
  readonly columns: ColumnMetadata[];
39
41
  readonly schema?: string;
40
42
  }
@@ -25,12 +25,38 @@ export declare abstract class DialectAdapterBase implements DialectAdapter {
25
25
  * Most dialects have explicit locks that can be used, like advisory locks
26
26
  * in PostgreSQL and the get_lock function in MySQL.
27
27
  *
28
- * If the dialect doesn't have explicit locks the {@link MIGRATION_LOCK_TABLE}
29
- * created by Kysely can be used instead. {@link MIGRATION_LOCK_TABLE}
30
- * has two columns `id` and `is_locked` and there's only one row in the
31
- * table whose id is {@link MIGRATION_LOCK_ID}. `is_locked` is an integer.
32
- * Kysely takes care of creating the lock table and inserting the one single
33
- * row to it before this method is executed.
28
+ * If the dialect doesn't have explicit locks the {@link MigrationLockOptions.lockTable}
29
+ * created by Kysely can be used instead. You can access it through the `options` object.
30
+ * The lock table has two columns `id` and `is_locked` and there's only one row in the table
31
+ * whose id is {@link MigrationLockOptions.lockRowId}. `is_locked` is an integer. Kysely
32
+ * takes care of creating the lock table and inserting the one single row to it before this
33
+ * method is executed. If the dialect supports schemas and the user has specified a custom
34
+ * schema in their migration settings, the options object also contains the schema name in
35
+ * {@link MigrationLockOptions.lockTableSchema}.
36
+ *
37
+ * Here's an example of how you might implement this method for a dialect that doesn't
38
+ * have explicit locks but supports `FOR UPDATE` row locks and transactional DDL:
39
+ *
40
+ * ```ts
41
+ * {
42
+ * async acquireMigrationLock(db, options): Promise<void> {
43
+ * const queryDb = options.lockTableSchema
44
+ * ? db.withSchema(options.lockTableSchema)
45
+ * : db
46
+ *
47
+ * // Since our imaginary dialect supports transactional DDL and has
48
+ * // row locks, we can simply take a row lock here and it will guarantee
49
+ * // all subsequent calls to this method from other transactions will
50
+ * // wait until this transaction finishes.
51
+ * await queryDb
52
+ * .selectFrom(options.lockTable)
53
+ * .selectAll()
54
+ * .where('id', '=', options.lockRowId)
55
+ * .forUpdate()
56
+ * .execute()
57
+ * }
58
+ * }
59
+ * ```
34
60
  *
35
61
  * If `supportsTransactionalDdl` is `true` then the `db` passed to this method
36
62
  * is a transaction inside which the migrations will be executed. Otherwise
@@ -26,19 +26,45 @@ export interface DialectAdapter {
26
26
  * Most dialects have explicit locks that can be used, like advisory locks
27
27
  * in PostgreSQL and the get_lock function in MySQL.
28
28
  *
29
- * If the dialect doesn't have explicit locks the {@link MIGRATION_LOCK_TABLE}
30
- * created by Kysely can be used instead. {@link MIGRATION_LOCK_TABLE}
31
- * has two columns `id` and `is_locked` and there's only one row in the
32
- * table whose id is {@link MIGRATION_LOCK_ID}. `is_locked` is an integer.
33
- * Kysely takes care of creating the lock table and inserting the one single
34
- * row to it before this method is executed.
29
+ * If the dialect doesn't have explicit locks the {@link MigrationLockOptions.lockTable}
30
+ * created by Kysely can be used instead. You can access it through the `options` object.
31
+ * The lock table has two columns `id` and `is_locked` and there's only one row in the table
32
+ * whose id is {@link MigrationLockOptions.lockRowId}. `is_locked` is an integer. Kysely
33
+ * takes care of creating the lock table and inserting the one single row to it before this
34
+ * method is executed. If the dialect supports schemas and the user has specified a custom
35
+ * schema in their migration settings, the options object also contains the schema name in
36
+ * {@link MigrationLockOptions.lockTableSchema}.
37
+ *
38
+ * Here's an example of how you might implement this method for a dialect that doesn't
39
+ * have explicit locks but supports `FOR UPDATE` row locks and transactional DDL:
40
+ *
41
+ * ```ts
42
+ * {
43
+ * async acquireMigrationLock(db, options): Promise<void> {
44
+ * const queryDb = options.lockTableSchema
45
+ * ? db.withSchema(options.lockTableSchema)
46
+ * : db
47
+ *
48
+ * // Since our imaginary dialect supports transactional DDL and has
49
+ * // row locks, we can simply take a row lock here and it will guarantee
50
+ * // all subsequent calls to this method from other transactions will
51
+ * // wait until this transaction finishes.
52
+ * await queryDb
53
+ * .selectFrom(options.lockTable)
54
+ * .selectAll()
55
+ * .where('id', '=', options.lockRowId)
56
+ * .forUpdate()
57
+ * .execute()
58
+ * }
59
+ * }
60
+ * ```
35
61
  *
36
62
  * If `supportsTransactionalDdl` is `true` then the `db` passed to this method
37
63
  * is a transaction inside which the migrations will be executed. Otherwise
38
64
  * `db` is a single connection (session) that will be used to execute the
39
65
  * migrations.
40
66
  */
41
- acquireMigrationLock(db: Kysely<any>): Promise<void>;
67
+ acquireMigrationLock(db: Kysely<any>, options: MigrationLockOptions): Promise<void>;
42
68
  /**
43
69
  * Releases the migration lock. See {@link acquireMigrationLock}.
44
70
  *
@@ -47,5 +73,21 @@ export interface DialectAdapter {
47
73
  * is a single connection (session) that was used to execute the migrations
48
74
  * and the `acquireMigrationLock` call.
49
75
  */
50
- releaseMigrationLock(db: Kysely<any>): Promise<void>;
76
+ releaseMigrationLock(db: Kysely<any>, options: MigrationLockOptions): Promise<void>;
77
+ }
78
+ export interface MigrationLockOptions {
79
+ /**
80
+ * The name of the migration lock table.
81
+ */
82
+ readonly lockTable: string;
83
+ /**
84
+ * The id of the only row in the migration lock table.
85
+ */
86
+ readonly lockRowId: string;
87
+ /**
88
+ * The schema in which the migration lock table lives. This is only
89
+ * defined if the user has specified a custom schema in the migration
90
+ * settings.
91
+ */
92
+ readonly lockTableSchema?: string;
51
93
  }
@@ -19,12 +19,38 @@ export declare class MysqlAdapter extends DialectAdapterBase {
19
19
  * Most dialects have explicit locks that can be used, like advisory locks
20
20
  * in PostgreSQL and the get_lock function in MySQL.
21
21
  *
22
- * If the dialect doesn't have explicit locks the {@link MIGRATION_LOCK_TABLE}
23
- * created by Kysely can be used instead. {@link MIGRATION_LOCK_TABLE}
24
- * has two columns `id` and `is_locked` and there's only one row in the
25
- * table whose id is {@link MIGRATION_LOCK_ID}. `is_locked` is an integer.
26
- * Kysely takes care of creating the lock table and inserting the one single
27
- * row to it before this method is executed.
22
+ * If the dialect doesn't have explicit locks the {@link MigrationLockOptions.lockTable}
23
+ * created by Kysely can be used instead. You can access it through the `options` object.
24
+ * The lock table has two columns `id` and `is_locked` and there's only one row in the table
25
+ * whose id is {@link MigrationLockOptions.lockRowId}. `is_locked` is an integer. Kysely
26
+ * takes care of creating the lock table and inserting the one single row to it before this
27
+ * method is executed. If the dialect supports schemas and the user has specified a custom
28
+ * schema in their migration settings, the options object also contains the schema name in
29
+ * {@link MigrationLockOptions.lockTableSchema}.
30
+ *
31
+ * Here's an example of how you might implement this method for a dialect that doesn't
32
+ * have explicit locks but supports `FOR UPDATE` row locks and transactional DDL:
33
+ *
34
+ * ```ts
35
+ * {
36
+ * async acquireMigrationLock(db, options): Promise<void> {
37
+ * const queryDb = options.lockTableSchema
38
+ * ? db.withSchema(options.lockTableSchema)
39
+ * : db
40
+ *
41
+ * // Since our imaginary dialect supports transactional DDL and has
42
+ * // row locks, we can simply take a row lock here and it will guarantee
43
+ * // all subsequent calls to this method from other transactions will
44
+ * // wait until this transaction finishes.
45
+ * await queryDb
46
+ * .selectFrom(options.lockTable)
47
+ * .selectAll()
48
+ * .where('id', '=', options.lockRowId)
49
+ * .forUpdate()
50
+ * .execute()
51
+ * }
52
+ * }
53
+ * ```
28
54
  *
29
55
  * If `supportsTransactionalDdl` is `true` then the `db` passed to this method
30
56
  * is a transaction inside which the migrations will be executed. Otherwise
@@ -8,7 +8,7 @@ export declare class MysqlIntrospector implements DatabaseIntrospector {
8
8
  */
9
9
  getSchemas(): Promise<SchemaMetadata[]>;
10
10
  /**
11
- * Get table metadata.
11
+ * Get tables and views metadata.
12
12
  */
13
13
  getTables(options?: DatabaseMetadataOptions): Promise<TableMetadata[]>;
14
14
  /**
@@ -13,30 +13,35 @@ class MysqlIntrospector {
13
13
  let rawSchemas = await this.#db
14
14
  .selectFrom('information_schema.schemata')
15
15
  .select('schema_name')
16
- .castTo()
16
+ .$castTo()
17
17
  .execute();
18
18
  return rawSchemas.map((it) => ({ name: it.SCHEMA_NAME }));
19
19
  }
20
20
  async getTables(options = { withInternalKyselyTables: false }) {
21
21
  let query = this.#db
22
- .selectFrom('information_schema.columns')
22
+ .selectFrom('information_schema.columns as columns')
23
+ .innerJoin('information_schema.tables as tables', (b) => b
24
+ .onRef('columns.TABLE_CATALOG', '=', 'tables.TABLE_CATALOG')
25
+ .onRef('columns.TABLE_SCHEMA', '=', 'tables.TABLE_SCHEMA')
26
+ .onRef('columns.TABLE_NAME', '=', 'tables.TABLE_NAME'))
23
27
  .select([
24
- 'COLUMN_NAME',
25
- 'COLUMN_DEFAULT',
26
- 'TABLE_NAME',
27
- 'TABLE_SCHEMA',
28
- 'IS_NULLABLE',
29
- 'DATA_TYPE',
30
- 'EXTRA',
28
+ 'columns.COLUMN_NAME',
29
+ 'columns.COLUMN_DEFAULT',
30
+ 'columns.TABLE_NAME',
31
+ 'columns.TABLE_SCHEMA',
32
+ 'tables.TABLE_TYPE',
33
+ 'columns.IS_NULLABLE',
34
+ 'columns.DATA_TYPE',
35
+ 'columns.EXTRA',
31
36
  ])
32
- .where('table_schema', '=', (0, sql_js_1.sql) `database()`)
33
- .orderBy('table_name')
34
- .orderBy('ordinal_position')
35
- .castTo();
37
+ .where('columns.TABLE_SCHEMA', '=', (0, sql_js_1.sql) `database()`)
38
+ .orderBy('columns.TABLE_NAME')
39
+ .orderBy('columns.ORDINAL_POSITION')
40
+ .$castTo();
36
41
  if (!options.withInternalKyselyTables) {
37
42
  query = query
38
- .where('table_name', '!=', migrator_js_1.DEFAULT_MIGRATION_TABLE)
39
- .where('table_name', '!=', migrator_js_1.DEFAULT_MIGRATION_LOCK_TABLE);
43
+ .where('columns.TABLE_NAME', '!=', migrator_js_1.DEFAULT_MIGRATION_TABLE)
44
+ .where('columns.TABLE_NAME', '!=', migrator_js_1.DEFAULT_MIGRATION_LOCK_TABLE);
40
45
  }
41
46
  const rawColumns = await query.execute();
42
47
  return this.#parseTableMetadata(rawColumns);
@@ -52,6 +57,7 @@ class MysqlIntrospector {
52
57
  if (!table) {
53
58
  table = (0, object_utils_js_1.freeze)({
54
59
  name: it.TABLE_NAME,
60
+ isView: it.TABLE_TYPE === 'VIEW',
55
61
  schema: it.TABLE_SCHEMA,
56
62
  columns: [],
57
63
  });
@@ -19,12 +19,38 @@ export declare class PostgresAdapter extends DialectAdapterBase {
19
19
  * Most dialects have explicit locks that can be used, like advisory locks
20
20
  * in PostgreSQL and the get_lock function in MySQL.
21
21
  *
22
- * If the dialect doesn't have explicit locks the {@link MIGRATION_LOCK_TABLE}
23
- * created by Kysely can be used instead. {@link MIGRATION_LOCK_TABLE}
24
- * has two columns `id` and `is_locked` and there's only one row in the
25
- * table whose id is {@link MIGRATION_LOCK_ID}. `is_locked` is an integer.
26
- * Kysely takes care of creating the lock table and inserting the one single
27
- * row to it before this method is executed.
22
+ * If the dialect doesn't have explicit locks the {@link MigrationLockOptions.lockTable}
23
+ * created by Kysely can be used instead. You can access it through the `options` object.
24
+ * The lock table has two columns `id` and `is_locked` and there's only one row in the table
25
+ * whose id is {@link MigrationLockOptions.lockRowId}. `is_locked` is an integer. Kysely
26
+ * takes care of creating the lock table and inserting the one single row to it before this
27
+ * method is executed. If the dialect supports schemas and the user has specified a custom
28
+ * schema in their migration settings, the options object also contains the schema name in
29
+ * {@link MigrationLockOptions.lockTableSchema}.
30
+ *
31
+ * Here's an example of how you might implement this method for a dialect that doesn't
32
+ * have explicit locks but supports `FOR UPDATE` row locks and transactional DDL:
33
+ *
34
+ * ```ts
35
+ * {
36
+ * async acquireMigrationLock(db, options): Promise<void> {
37
+ * const queryDb = options.lockTableSchema
38
+ * ? db.withSchema(options.lockTableSchema)
39
+ * : db
40
+ *
41
+ * // Since our imaginary dialect supports transactional DDL and has
42
+ * // row locks, we can simply take a row lock here and it will guarantee
43
+ * // all subsequent calls to this method from other transactions will
44
+ * // wait until this transaction finishes.
45
+ * await queryDb
46
+ * .selectFrom(options.lockTable)
47
+ * .selectAll()
48
+ * .where('id', '=', options.lockRowId)
49
+ * .forUpdate()
50
+ * .execute()
51
+ * }
52
+ * }
53
+ * ```
28
54
  *
29
55
  * If `supportsTransactionalDdl` is `true` then the `db` passed to this method
30
56
  * is a transaction inside which the migrations will be executed. Otherwise
@@ -8,7 +8,7 @@ export declare class PostgresIntrospector implements DatabaseIntrospector {
8
8
  */
9
9
  getSchemas(): Promise<SchemaMetadata[]>;
10
10
  /**
11
- * Get table metadata.
11
+ * Get tables and views metadata.
12
12
  */
13
13
  getTables(options?: DatabaseMetadataOptions): Promise<TableMetadata[]>;
14
14
  /**
@@ -13,7 +13,7 @@ class PostgresIntrospector {
13
13
  let rawSchemas = await this.#db
14
14
  .selectFrom('pg_catalog.pg_namespace')
15
15
  .select('nspname')
16
- .castTo()
16
+ .$castTo()
17
17
  .execute();
18
18
  return rawSchemas.map((it) => ({ name: it.nspname }));
19
19
  }
@@ -34,6 +34,7 @@ class PostgresIntrospector {
34
34
  'a.attnotnull as not_null',
35
35
  'a.atthasdef as has_default',
36
36
  'c.relname as table',
37
+ 'c.relkind as table_type',
37
38
  'ns.nspname as schema',
38
39
  'typ.typname as type',
39
40
  'dtns.nspname as type_schema',
@@ -49,7 +50,7 @@ class PostgresIntrospector {
49
50
  .as('auto_incrementing'),
50
51
  ])
51
52
  // r == normal table
52
- .where('c.relkind', '=', 'r')
53
+ .where('c.relkind', 'in', ['r', 'v'])
53
54
  .where('ns.nspname', '!~', '^pg_')
54
55
  .where('ns.nspname', '!=', 'information_schema')
55
56
  // No system columns
@@ -58,7 +59,7 @@ class PostgresIntrospector {
58
59
  .orderBy('ns.nspname')
59
60
  .orderBy('c.relname')
60
61
  .orderBy('a.attnum')
61
- .castTo();
62
+ .$castTo();
62
63
  if (!options.withInternalKyselyTables) {
63
64
  query = query
64
65
  .where('c.relname', '!=', migrator_js_1.DEFAULT_MIGRATION_TABLE)
@@ -78,6 +79,7 @@ class PostgresIntrospector {
78
79
  if (!table) {
79
80
  table = (0, object_utils_js_1.freeze)({
80
81
  name: it.table,
82
+ isView: it.table_type === 'v',
81
83
  schema: it.schema,
82
84
  columns: [],
83
85
  });
@@ -18,12 +18,38 @@ export declare class SqliteAdapter implements DialectAdapterBase {
18
18
  * Most dialects have explicit locks that can be used, like advisory locks
19
19
  * in PostgreSQL and the get_lock function in MySQL.
20
20
  *
21
- * If the dialect doesn't have explicit locks the {@link MIGRATION_LOCK_TABLE}
22
- * created by Kysely can be used instead. {@link MIGRATION_LOCK_TABLE}
23
- * has two columns `id` and `is_locked` and there's only one row in the
24
- * table whose id is {@link MIGRATION_LOCK_ID}. `is_locked` is an integer.
25
- * Kysely takes care of creating the lock table and inserting the one single
26
- * row to it before this method is executed.
21
+ * If the dialect doesn't have explicit locks the {@link MigrationLockOptions.lockTable}
22
+ * created by Kysely can be used instead. You can access it through the `options` object.
23
+ * The lock table has two columns `id` and `is_locked` and there's only one row in the table
24
+ * whose id is {@link MigrationLockOptions.lockRowId}. `is_locked` is an integer. Kysely
25
+ * takes care of creating the lock table and inserting the one single row to it before this
26
+ * method is executed. If the dialect supports schemas and the user has specified a custom
27
+ * schema in their migration settings, the options object also contains the schema name in
28
+ * {@link MigrationLockOptions.lockTableSchema}.
29
+ *
30
+ * Here's an example of how you might implement this method for a dialect that doesn't
31
+ * have explicit locks but supports `FOR UPDATE` row locks and transactional DDL:
32
+ *
33
+ * ```ts
34
+ * {
35
+ * async acquireMigrationLock(db, options): Promise<void> {
36
+ * const queryDb = options.lockTableSchema
37
+ * ? db.withSchema(options.lockTableSchema)
38
+ * : db
39
+ *
40
+ * // Since our imaginary dialect supports transactional DDL and has
41
+ * // row locks, we can simply take a row lock here and it will guarantee
42
+ * // all subsequent calls to this method from other transactions will
43
+ * // wait until this transaction finishes.
44
+ * await queryDb
45
+ * .selectFrom(options.lockTable)
46
+ * .selectAll()
47
+ * .where('id', '=', options.lockRowId)
48
+ * .forUpdate()
49
+ * .execute()
50
+ * }
51
+ * }
52
+ * ```
27
53
  *
28
54
  * If `supportsTransactionalDdl` is `true` then the `db` passed to this method
29
55
  * is a transaction inside which the migrations will be executed. Otherwise
@@ -8,7 +8,7 @@ export declare class SqliteIntrospector implements DatabaseIntrospector {
8
8
  */
9
9
  getSchemas(): Promise<SchemaMetadata[]>;
10
10
  /**
11
- * Get table metadata.
11
+ * Get tables and views metadata.
12
12
  */
13
13
  getTables(options?: DatabaseMetadataOptions): Promise<TableMetadata[]>;
14
14
  /**
@@ -15,11 +15,11 @@ class SqliteIntrospector {
15
15
  async getTables(options = { withInternalKyselyTables: false }) {
16
16
  let query = this.#db
17
17
  .selectFrom('sqlite_schema')
18
- .where('type', '=', 'table')
18
+ .where('type', 'in', ['table', 'view'])
19
19
  .where('name', 'not like', 'sqlite_%')
20
20
  .select('name')
21
21
  .orderBy('name')
22
- .castTo();
22
+ .$castTo();
23
23
  if (!options.withInternalKyselyTables) {
24
24
  query = query
25
25
  .where('name', '!=', migrator_js_1.DEFAULT_MIGRATION_TABLE)
@@ -36,14 +36,14 @@ class SqliteIntrospector {
36
36
  async #getTableMetadata(table) {
37
37
  const db = this.#db;
38
38
  // Get the SQL that was used to create the table.
39
- const createSql = await db
39
+ const tableDefinition = await db
40
40
  .selectFrom('sqlite_master')
41
41
  .where('name', '=', table)
42
- .select('sql')
43
- .castTo()
44
- .execute();
42
+ .select(['sql', 'type'])
43
+ .$castTo()
44
+ .executeTakeFirstOrThrow();
45
45
  // Try to find the name of the column that has `autoincrement` 🤦
46
- const autoIncrementCol = createSql[0]?.sql
46
+ const autoIncrementCol = tableDefinition.sql
47
47
  ?.split(/[\(\),]/)
48
48
  ?.find((it) => it.toLowerCase().includes('autoincrement'))
49
49
  ?.trimStart()
@@ -56,6 +56,7 @@ class SqliteIntrospector {
56
56
  .execute();
57
57
  return {
58
58
  name: table,
59
+ isView: tableDefinition.type === 'view',
59
60
  columns: columns.map((col) => ({
60
61
  name: col.name,
61
62
  dataType: col.type,
@@ -159,6 +159,7 @@ export * from './operation-node/partition-by-item-node.js';
159
159
  export * from './operation-node/set-operation-node.js';
160
160
  export * from './operation-node/binary-operation-node.js';
161
161
  export * from './operation-node/unary-operation-node.js';
162
+ export * from './operation-node/using-node.js';
162
163
  export * from './util/column-type.js';
163
164
  export * from './util/compilable.js';
164
165
  export * from './util/explainable.js';
package/dist/cjs/index.js CHANGED
@@ -176,6 +176,7 @@ __exportStar(require("./operation-node/partition-by-item-node.js"), exports);
176
176
  __exportStar(require("./operation-node/set-operation-node.js"), exports);
177
177
  __exportStar(require("./operation-node/binary-operation-node.js"), exports);
178
178
  __exportStar(require("./operation-node/unary-operation-node.js"), exports);
179
+ __exportStar(require("./operation-node/using-node.js"), exports);
179
180
  __exportStar(require("./util/column-type.js"), exports);
180
181
  __exportStar(require("./util/compilable.js"), exports);
181
182
  __exportStar(require("./util/explainable.js"), exports);
@@ -24,12 +24,17 @@ export interface Migration {
24
24
  * other way.
25
25
  *
26
26
  * ```ts
27
+ * import { promises as fs } from 'fs'
28
+ * import path from 'path'
29
+ *
27
30
  * const migrator = new Migrator({
28
31
  * db,
29
- * provider: new FileMigrationProvider(
32
+ * provider: new FileMigrationProvider({
33
+ * fs,
34
+ * path,
30
35
  * // Path to the folder that contains all your migrations.
31
- * 'some/path/to/migrations'
32
- * )
36
+ * migrationFolder: 'some/path/to/migrations'
37
+ * })
33
38
  * })
34
39
  * ```
35
40
  */
@@ -19,12 +19,17 @@ exports.NO_MIGRATIONS = (0, object_utils_js_1.freeze)({ __noMigrations__: true }
19
19
  * other way.
20
20
  *
21
21
  * ```ts
22
+ * import { promises as fs } from 'fs'
23
+ * import path from 'path'
24
+ *
22
25
  * const migrator = new Migrator({
23
26
  * db,
24
- * provider: new FileMigrationProvider(
27
+ * provider: new FileMigrationProvider({
28
+ * fs,
29
+ * path,
25
30
  * // Path to the folder that contains all your migrations.
26
- * 'some/path/to/migrations'
27
- * )
31
+ * migrationFolder: 'some/path/to/migrations'
32
+ * })
28
33
  * })
29
34
  * ```
30
35
  */
@@ -318,9 +323,14 @@ class Migrator {
318
323
  }
319
324
  async #runMigrations(getTargetMigrationIndex) {
320
325
  const adapter = this.#props.db.getExecutor().adapter;
326
+ const lockOptions = (0, object_utils_js_1.freeze)({
327
+ lockTable: this.#props.migrationLockTableName ?? exports.DEFAULT_MIGRATION_LOCK_TABLE,
328
+ lockRowId: exports.MIGRATION_LOCK_ID,
329
+ lockTableSchema: this.#props.migrationTableSchema,
330
+ });
321
331
  const run = async (db) => {
322
332
  try {
323
- await adapter.acquireMigrationLock(db);
333
+ await adapter.acquireMigrationLock(db, lockOptions);
324
334
  const state = await this.#getState(db);
325
335
  if (state.migrations.length === 0) {
326
336
  return { results: [] };
@@ -338,7 +348,7 @@ class Migrator {
338
348
  return { results: [] };
339
349
  }
340
350
  finally {
341
- await adapter.releaseMigrationLock(db);
351
+ await adapter.releaseMigrationLock(db, lockOptions);
342
352
  }
343
353
  };
344
354
  if (adapter.supportsTransactionalDdl) {