kysely 0.19.5 → 0.19.6

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.
@@ -1,4 +1,3 @@
1
- import { ColumnDataType } from '../operation-node/data-type-node.js';
2
1
  /**
3
2
  * An interface for getting the database metadata (names of the tables and columns etc.)
4
3
  */
@@ -41,6 +40,16 @@ export interface TableMetadata {
41
40
  }
42
41
  export interface ColumnMetadata {
43
42
  readonly name: string;
44
- readonly dataType: ColumnDataType;
43
+ /**
44
+ * The data type of the column as reported by the database.
45
+ *
46
+ * NOTE: This value is whatever the database engine returns and it will be
47
+ * different on different dialects even if you run the same migrations.
48
+ * For example `integer` datatype in a migration will produce `int4`
49
+ * on PostgreSQL, `INTEGER` on SQLite and `int` on MySQL.
50
+ */
51
+ readonly dataType: string;
52
+ readonly isAutoIncrementing: boolean;
45
53
  readonly isNullable: boolean;
54
+ readonly hasDefaultValue: boolean;
46
55
  }
@@ -22,10 +22,12 @@ class MysqlIntrospector {
22
22
  .selectFrom('information_schema.columns')
23
23
  .select([
24
24
  'column_name',
25
+ 'column_default',
25
26
  'table_name',
26
27
  'table_schema',
27
28
  'is_nullable',
28
29
  'data_type',
30
+ 'extra',
29
31
  ])
30
32
  .where('table_schema', '=', (0, sql_js_1.sql) `database()`)
31
33
  .castTo();
@@ -57,6 +59,8 @@ class MysqlIntrospector {
57
59
  name: it.COLUMN_NAME,
58
60
  dataType: it.DATA_TYPE,
59
61
  isNullable: it.IS_NULLABLE === 'YES',
62
+ isAutoIncrementing: it.EXTRA.toLowerCase().includes('auto_increment'),
63
+ hasDefaultValue: it.COLUMN_DEFAULT !== null,
60
64
  }));
61
65
  return tables;
62
66
  }, []);
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PostgresIntrospector = void 0;
4
4
  const migrator_js_1 = require("../../migration/migrator.js");
5
5
  const object_utils_js_1 = require("../../util/object-utils.js");
6
+ const sql_js_1 = require("../../raw-builder/sql.js");
6
7
  class PostgresIntrospector {
7
8
  #db;
8
9
  constructor(db) {
@@ -25,9 +26,18 @@ class PostgresIntrospector {
25
26
  .select([
26
27
  'a.attname as column',
27
28
  'a.attnotnull as not_null',
29
+ 'a.atthasdef as has_default',
28
30
  't.tablename as table',
29
31
  't.schemaname as schema',
30
32
  'typ.typname as type',
33
+ // Detect if the column is auto incrementing by finding the sequence
34
+ // that is created for `serial` and `bigserial` columns.
35
+ this.#db
36
+ .selectFrom('pg_class')
37
+ .select((0, sql_js_1.sql) `true`.as('auto_incrementing'))
38
+ .where('relkind', '=', 'S')
39
+ .where('relname', '=', (0, sql_js_1.sql) `t.tablename || '_' || a.attname || '_seq'`)
40
+ .as('auto_incrementing'),
31
41
  ])
32
42
  .where('t.schemaname', '!~', '^pg_')
33
43
  .where('t.schemaname', '!=', 'information_schema')
@@ -62,6 +72,8 @@ class PostgresIntrospector {
62
72
  name: it.column,
63
73
  dataType: it.type,
64
74
  isNullable: !it.not_null,
75
+ isAutoIncrementing: !!it.auto_incrementing,
76
+ hasDefaultValue: it.has_default,
65
77
  }));
66
78
  return tables;
67
79
  }, []);
@@ -34,9 +34,22 @@ class SqliteIntrospector {
34
34
  }
35
35
  async #getTableMetadata(table) {
36
36
  const db = this.#db;
37
+ // Get the SQL that was used to create the table.
38
+ const createSql = await db
39
+ .selectFrom('sqlite_master')
40
+ .where('name', '=', table)
41
+ .select('sql')
42
+ .castTo()
43
+ .execute();
44
+ // Try to find the name of the column that has `autoincrement` 🤦
45
+ const autoIncrementCol = createSql[0]?.sql
46
+ ?.split(/[\(\),]/)
47
+ ?.find((it) => it.toLowerCase().includes('autoincrement'))
48
+ ?.split(/\s+/)?.[0]
49
+ ?.replace(/["`]/g, '');
37
50
  const columns = await db
38
- .selectFrom((0, sql_js_1.sql) `PRAGMA_TABLE_INFO(${table})`.as('table_info'))
39
- .select(['name', 'type', 'notnull'])
51
+ .selectFrom((0, sql_js_1.sql) `pragma_table_info(${table})`.as('table_info'))
52
+ .select(['name', 'type', 'notnull', 'dflt_value'])
40
53
  .execute();
41
54
  return {
42
55
  name: table,
@@ -44,6 +57,8 @@ class SqliteIntrospector {
44
57
  name: col.name,
45
58
  dataType: col.type,
46
59
  isNullable: !col.notnull,
60
+ isAutoIncrementing: col.name === autoIncrementCol,
61
+ hasDefaultValue: !!col.dflt_value,
47
62
  })),
48
63
  };
49
64
  }
@@ -66,6 +66,10 @@ export declare class JoinBuilder<DB, TB extends keyof DB> implements OperationNo
66
66
  * See {@link WhereInterface.orWhereNotExists} for documentation and examples.
67
67
  */
68
68
  orOnNotExists(arg: ExistsExpression<DB, TB>): JoinBuilder<DB, TB>;
69
+ /**
70
+ * Adds `on true`.
71
+ */
72
+ onTrue(): JoinBuilder<DB, TB>;
69
73
  toOperationNode(): JoinNode;
70
74
  }
71
75
  export interface JoinBuilderProps {
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.JoinBuilder = void 0;
4
4
  const join_node_js_1 = require("../operation-node/join-node.js");
5
+ const raw_node_js_1 = require("../operation-node/raw-node.js");
5
6
  const filter_parser_js_1 = require("../parser/filter-parser.js");
6
7
  const object_utils_js_1 = require("../util/object-utils.js");
7
8
  const prevent_await_js_1 = require("../util/prevent-await.js");
@@ -94,6 +95,15 @@ class JoinBuilder {
94
95
  joinNode: join_node_js_1.JoinNode.cloneWithOrOn(this.#props.joinNode, (0, filter_parser_js_1.parseNotExistFilter)(arg)),
95
96
  });
96
97
  }
98
+ /**
99
+ * Adds `on true`.
100
+ */
101
+ onTrue() {
102
+ return new JoinBuilder({
103
+ ...this.#props,
104
+ joinNode: join_node_js_1.JoinNode.cloneWithOn(this.#props.joinNode, raw_node_js_1.RawNode.createWithSql('true')),
105
+ });
106
+ }
97
107
  toOperationNode() {
98
108
  return this.#props.joinNode;
99
109
  }
@@ -875,11 +875,41 @@ export declare class SelectQueryBuilder<DB, TB extends keyof DB, O> implements W
875
875
  fullJoin<TE extends TableExpression<DB, TB>, FN extends JoinCallbackExpression<DB, TB, TE>>(table: TE, callback: FN): SelectQueryBuilderWithFullJoin<DB, TB, O, TE>;
876
876
  /**
877
877
  * Just like {@link innerJoin} but adds a lateral join instead of an inner join.
878
+ *
879
+ * ### Examples
880
+ *
881
+ * ```ts
882
+ * db.selectFrom('person')
883
+ * .innerJoinLateral(
884
+ * (eb) =>
885
+ * eb.selectFrom('pet')
886
+ * .select('name')
887
+ * .whereRef('pet.owner_id', '=', 'person.id')
888
+ * .as('p'),
889
+ * (join) => join.onTrue()
890
+ * )
891
+ * .select(['first_name', 'p.name'])
892
+ * .orderBy('first_name')
878
893
  */
879
894
  innerJoinLateral<TE extends TableExpression<DB, TB>, K1 extends JoinReferenceExpression<DB, TB, TE>, K2 extends JoinReferenceExpression<DB, TB, TE>>(table: TE, k1: K1, k2: K2): SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>;
880
895
  innerJoinLateral<TE extends TableExpression<DB, TB>, FN extends JoinCallbackExpression<DB, TB, TE>>(table: TE, callback: FN): SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>;
881
896
  /**
882
897
  * Just like {@link innerJoin} but adds a lateral left join instead of an inner join.
898
+ * ### Examples
899
+ *
900
+ * ```ts
901
+ * db.selectFrom('person')
902
+ * .leftJoinLateral(
903
+ * (eb) =>
904
+ * eb.selectFrom('pet')
905
+ * .select('name')
906
+ * .whereRef('pet.owner_id', '=', 'person.id')
907
+ * .as('p'),
908
+ * (join) => join.onTrue()
909
+ * )
910
+ * .select(['first_name', 'p.name'])
911
+ * .orderBy('first_name')
912
+ * ```
883
913
  */
884
914
  leftJoinLateral<TE extends TableExpression<DB, TB>, K1 extends JoinReferenceExpression<DB, TB, TE>, K2 extends JoinReferenceExpression<DB, TB, TE>>(table: TE, k1: K1, k2: K2): SelectQueryBuilderWithLeftJoin<DB, TB, O, TE>;
885
915
  leftJoinLateral<TE extends TableExpression<DB, TB>, FN extends JoinCallbackExpression<DB, TB, TE>>(table: TE, callback: FN): SelectQueryBuilderWithLeftJoin<DB, TB, O, TE>;
@@ -1,4 +1,3 @@
1
- import { ColumnDataType } from '../operation-node/data-type-node.js';
2
1
  /**
3
2
  * An interface for getting the database metadata (names of the tables and columns etc.)
4
3
  */
@@ -41,6 +40,16 @@ export interface TableMetadata {
41
40
  }
42
41
  export interface ColumnMetadata {
43
42
  readonly name: string;
44
- readonly dataType: ColumnDataType;
43
+ /**
44
+ * The data type of the column as reported by the database.
45
+ *
46
+ * NOTE: This value is whatever the database engine returns and it will be
47
+ * different on different dialects even if you run the same migrations.
48
+ * For example `integer` datatype in a migration will produce `int4`
49
+ * on PostgreSQL, `INTEGER` on SQLite and `int` on MySQL.
50
+ */
51
+ readonly dataType: string;
52
+ readonly isAutoIncrementing: boolean;
45
53
  readonly isNullable: boolean;
54
+ readonly hasDefaultValue: boolean;
46
55
  }
@@ -20,10 +20,12 @@ export class MysqlIntrospector {
20
20
  .selectFrom('information_schema.columns')
21
21
  .select([
22
22
  'column_name',
23
+ 'column_default',
23
24
  'table_name',
24
25
  'table_schema',
25
26
  'is_nullable',
26
27
  'data_type',
28
+ 'extra',
27
29
  ])
28
30
  .where('table_schema', '=', sql `database()`)
29
31
  .castTo();
@@ -55,6 +57,8 @@ export class MysqlIntrospector {
55
57
  name: it.COLUMN_NAME,
56
58
  dataType: it.DATA_TYPE,
57
59
  isNullable: it.IS_NULLABLE === 'YES',
60
+ isAutoIncrementing: it.EXTRA.toLowerCase().includes('auto_increment'),
61
+ hasDefaultValue: it.COLUMN_DEFAULT !== null,
58
62
  }));
59
63
  return tables;
60
64
  }, []);
@@ -1,6 +1,7 @@
1
1
  /// <reference types="./postgres-introspector.d.ts" />
2
2
  import { DEFAULT_MIGRATION_LOCK_TABLE, DEFAULT_MIGRATION_TABLE, } from '../../migration/migrator.js';
3
3
  import { freeze } from '../../util/object-utils.js';
4
+ import { sql } from '../../raw-builder/sql.js';
4
5
  export class PostgresIntrospector {
5
6
  #db;
6
7
  constructor(db) {
@@ -23,9 +24,18 @@ export class PostgresIntrospector {
23
24
  .select([
24
25
  'a.attname as column',
25
26
  'a.attnotnull as not_null',
27
+ 'a.atthasdef as has_default',
26
28
  't.tablename as table',
27
29
  't.schemaname as schema',
28
30
  'typ.typname as type',
31
+ // Detect if the column is auto incrementing by finding the sequence
32
+ // that is created for `serial` and `bigserial` columns.
33
+ this.#db
34
+ .selectFrom('pg_class')
35
+ .select(sql `true`.as('auto_incrementing'))
36
+ .where('relkind', '=', 'S')
37
+ .where('relname', '=', sql `t.tablename || '_' || a.attname || '_seq'`)
38
+ .as('auto_incrementing'),
29
39
  ])
30
40
  .where('t.schemaname', '!~', '^pg_')
31
41
  .where('t.schemaname', '!=', 'information_schema')
@@ -60,6 +70,8 @@ export class PostgresIntrospector {
60
70
  name: it.column,
61
71
  dataType: it.type,
62
72
  isNullable: !it.not_null,
73
+ isAutoIncrementing: !!it.auto_incrementing,
74
+ hasDefaultValue: it.has_default,
63
75
  }));
64
76
  return tables;
65
77
  }, []);
@@ -32,9 +32,22 @@ export class SqliteIntrospector {
32
32
  }
33
33
  async #getTableMetadata(table) {
34
34
  const db = this.#db;
35
+ // Get the SQL that was used to create the table.
36
+ const createSql = await db
37
+ .selectFrom('sqlite_master')
38
+ .where('name', '=', table)
39
+ .select('sql')
40
+ .castTo()
41
+ .execute();
42
+ // Try to find the name of the column that has `autoincrement` 🤦
43
+ const autoIncrementCol = createSql[0]?.sql
44
+ ?.split(/[\(\),]/)
45
+ ?.find((it) => it.toLowerCase().includes('autoincrement'))
46
+ ?.split(/\s+/)?.[0]
47
+ ?.replace(/["`]/g, '');
35
48
  const columns = await db
36
- .selectFrom(sql `PRAGMA_TABLE_INFO(${table})`.as('table_info'))
37
- .select(['name', 'type', 'notnull'])
49
+ .selectFrom(sql `pragma_table_info(${table})`.as('table_info'))
50
+ .select(['name', 'type', 'notnull', 'dflt_value'])
38
51
  .execute();
39
52
  return {
40
53
  name: table,
@@ -42,6 +55,8 @@ export class SqliteIntrospector {
42
55
  name: col.name,
43
56
  dataType: col.type,
44
57
  isNullable: !col.notnull,
58
+ isAutoIncrementing: col.name === autoIncrementCol,
59
+ hasDefaultValue: !!col.dflt_value,
45
60
  })),
46
61
  };
47
62
  }
@@ -66,6 +66,10 @@ export declare class JoinBuilder<DB, TB extends keyof DB> implements OperationNo
66
66
  * See {@link WhereInterface.orWhereNotExists} for documentation and examples.
67
67
  */
68
68
  orOnNotExists(arg: ExistsExpression<DB, TB>): JoinBuilder<DB, TB>;
69
+ /**
70
+ * Adds `on true`.
71
+ */
72
+ onTrue(): JoinBuilder<DB, TB>;
69
73
  toOperationNode(): JoinNode;
70
74
  }
71
75
  export interface JoinBuilderProps {
@@ -1,5 +1,6 @@
1
1
  /// <reference types="./join-builder.d.ts" />
2
2
  import { JoinNode } from '../operation-node/join-node.js';
3
+ import { RawNode } from '../operation-node/raw-node.js';
3
4
  import { parseExistFilter, parseNotExistFilter, parseOnFilter, parseReferenceFilter, } from '../parser/filter-parser.js';
4
5
  import { freeze } from '../util/object-utils.js';
5
6
  import { preventAwait } from '../util/prevent-await.js';
@@ -92,6 +93,15 @@ export class JoinBuilder {
92
93
  joinNode: JoinNode.cloneWithOrOn(this.#props.joinNode, parseNotExistFilter(arg)),
93
94
  });
94
95
  }
96
+ /**
97
+ * Adds `on true`.
98
+ */
99
+ onTrue() {
100
+ return new JoinBuilder({
101
+ ...this.#props,
102
+ joinNode: JoinNode.cloneWithOn(this.#props.joinNode, RawNode.createWithSql('true')),
103
+ });
104
+ }
95
105
  toOperationNode() {
96
106
  return this.#props.joinNode;
97
107
  }
@@ -875,11 +875,41 @@ export declare class SelectQueryBuilder<DB, TB extends keyof DB, O> implements W
875
875
  fullJoin<TE extends TableExpression<DB, TB>, FN extends JoinCallbackExpression<DB, TB, TE>>(table: TE, callback: FN): SelectQueryBuilderWithFullJoin<DB, TB, O, TE>;
876
876
  /**
877
877
  * Just like {@link innerJoin} but adds a lateral join instead of an inner join.
878
+ *
879
+ * ### Examples
880
+ *
881
+ * ```ts
882
+ * db.selectFrom('person')
883
+ * .innerJoinLateral(
884
+ * (eb) =>
885
+ * eb.selectFrom('pet')
886
+ * .select('name')
887
+ * .whereRef('pet.owner_id', '=', 'person.id')
888
+ * .as('p'),
889
+ * (join) => join.onTrue()
890
+ * )
891
+ * .select(['first_name', 'p.name'])
892
+ * .orderBy('first_name')
878
893
  */
879
894
  innerJoinLateral<TE extends TableExpression<DB, TB>, K1 extends JoinReferenceExpression<DB, TB, TE>, K2 extends JoinReferenceExpression<DB, TB, TE>>(table: TE, k1: K1, k2: K2): SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>;
880
895
  innerJoinLateral<TE extends TableExpression<DB, TB>, FN extends JoinCallbackExpression<DB, TB, TE>>(table: TE, callback: FN): SelectQueryBuilderWithInnerJoin<DB, TB, O, TE>;
881
896
  /**
882
897
  * Just like {@link innerJoin} but adds a lateral left join instead of an inner join.
898
+ * ### Examples
899
+ *
900
+ * ```ts
901
+ * db.selectFrom('person')
902
+ * .leftJoinLateral(
903
+ * (eb) =>
904
+ * eb.selectFrom('pet')
905
+ * .select('name')
906
+ * .whereRef('pet.owner_id', '=', 'person.id')
907
+ * .as('p'),
908
+ * (join) => join.onTrue()
909
+ * )
910
+ * .select(['first_name', 'p.name'])
911
+ * .orderBy('first_name')
912
+ * ```
883
913
  */
884
914
  leftJoinLateral<TE extends TableExpression<DB, TB>, K1 extends JoinReferenceExpression<DB, TB, TE>, K2 extends JoinReferenceExpression<DB, TB, TE>>(table: TE, k1: K1, k2: K2): SelectQueryBuilderWithLeftJoin<DB, TB, O, TE>;
885
915
  leftJoinLateral<TE extends TableExpression<DB, TB>, FN extends JoinCallbackExpression<DB, TB, TE>>(table: TE, callback: FN): SelectQueryBuilderWithLeftJoin<DB, TB, O, TE>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kysely",
3
- "version": "0.19.5",
3
+ "version": "0.19.6",
4
4
  "description": "Type safe SQL query builder",
5
5
  "repository": {
6
6
  "type": "git",