@h3ravel/arquebus 0.3.6 → 0.4.1
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.
- package/bin/index.cjs +4365 -2840
- package/bin/index.js +4373 -2848
- package/dist/browser/index.cjs +2 -0
- package/dist/browser/index.d.cts +94 -7
- package/dist/browser/index.d.ts +94 -7
- package/dist/browser/index.js +2 -1
- package/dist/index.cjs +1499 -24
- package/dist/index.d.cts +129 -10
- package/dist/index.d.ts +129 -10
- package/dist/index.js +1500 -26
- package/dist/inspector/index.cjs +4885 -0
- package/dist/inspector/index.d.cts +83 -0
- package/dist/inspector/index.d.ts +83 -0
- package/dist/inspector/index.js +4859 -0
- package/dist/migrations/index.cjs +4386 -2912
- package/dist/migrations/index.d.cts +127 -9
- package/dist/migrations/index.d.ts +128 -10
- package/dist/migrations/index.js +4265 -2791
- package/package.json +27 -18
- package/types/query-builder.ts +37 -1
- package/src/migrations/stubs/migration-js.stub +0 -21
- package/src/migrations/stubs/migration-ts.stub +0 -18
- package/src/migrations/stubs/migration.create-js.stub +0 -24
- package/src/migrations/stubs/migration.create-ts.stub +0 -21
- package/src/migrations/stubs/migration.update-js.stub +0 -25
- package/src/migrations/stubs/migration.update-ts.stub +0 -22
- package/src/stubs/arquebus.config-js.stub +0 -25
- package/src/stubs/arquebus.config-ts.stub +0 -24
- package/src/stubs/model-js.stub +0 -5
- package/src/stubs/model-ts.stub +0 -5
package/dist/index.cjs
CHANGED
|
@@ -239,6 +239,7 @@ const tap = (instance, callback) => {
|
|
|
239
239
|
return result instanceof Promise ? result.then(() => instance) : instance;
|
|
240
240
|
};
|
|
241
241
|
const { compose } = mixin_exports;
|
|
242
|
+
const flatten = (arr) => arr.flat();
|
|
242
243
|
const flattenDeep = (arr) => Array.isArray(arr) ? arr.reduce((a, b) => a.concat(flattenDeep(b)), []) : [arr];
|
|
243
244
|
const kebabCase = (str) => (0, radashi.trim)((0, radashi.dash)(str.replace(/[^a-zA-Z0-9_-]/g, "-")), "_-");
|
|
244
245
|
const snakeCase = (str) => (0, radashi.trim)((0, radashi.snake)(str.replace(/[^a-zA-Z0-9_-]/g, "-")), "_-");
|
|
@@ -3557,13 +3558,1430 @@ var MigrationRepository = class {
|
|
|
3557
3558
|
return this.getConnection().table(this.table);
|
|
3558
3559
|
}
|
|
3559
3560
|
getConnection() {
|
|
3560
|
-
return this.resolver.
|
|
3561
|
+
return this.resolver.fire(this.connection);
|
|
3561
3562
|
}
|
|
3562
3563
|
setSource(name) {
|
|
3563
3564
|
this.connection = name;
|
|
3564
3565
|
}
|
|
3565
3566
|
};
|
|
3566
3567
|
|
|
3568
|
+
//#endregion
|
|
3569
|
+
//#region src/inspector/utils/strip-quotes.ts
|
|
3570
|
+
/**
|
|
3571
|
+
* Strip leading/trailing quotes from a string and handle null values.
|
|
3572
|
+
*/
|
|
3573
|
+
function stripQuotes(value) {
|
|
3574
|
+
if (value === null || value === void 0) return null;
|
|
3575
|
+
const trimmed = value.trim();
|
|
3576
|
+
if (trimmed.startsWith("'") && trimmed.endsWith("'") || trimmed.startsWith("\"") && trimmed.endsWith("\"")) return trimmed.slice(1, -1);
|
|
3577
|
+
return value;
|
|
3578
|
+
}
|
|
3579
|
+
|
|
3580
|
+
//#endregion
|
|
3581
|
+
//#region src/inspector/dialects/cockroachdb.ts
|
|
3582
|
+
/**
|
|
3583
|
+
* Converts CockroachDB default value to JS
|
|
3584
|
+
* Eg `'example'::character varying` => `example`
|
|
3585
|
+
*/
|
|
3586
|
+
function parseDefaultValue$5(value) {
|
|
3587
|
+
if (value === null) return null;
|
|
3588
|
+
if (value.startsWith("nextval(")) return value;
|
|
3589
|
+
value = value.split("::")[0];
|
|
3590
|
+
return stripQuotes(value);
|
|
3591
|
+
}
|
|
3592
|
+
var CockroachDB = class {
|
|
3593
|
+
knex;
|
|
3594
|
+
schema;
|
|
3595
|
+
explodedSchema;
|
|
3596
|
+
constructor(knex$1) {
|
|
3597
|
+
this.knex = knex$1;
|
|
3598
|
+
const config = knex$1.client.config;
|
|
3599
|
+
if (!config.searchPath) {
|
|
3600
|
+
this.schema = "public";
|
|
3601
|
+
this.explodedSchema = [this.schema];
|
|
3602
|
+
} else if (typeof config.searchPath === "string") {
|
|
3603
|
+
this.schema = config.searchPath;
|
|
3604
|
+
this.explodedSchema = [config.searchPath];
|
|
3605
|
+
} else {
|
|
3606
|
+
this.schema = config.searchPath[0];
|
|
3607
|
+
this.explodedSchema = config.searchPath;
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3610
|
+
/**
|
|
3611
|
+
* Set the schema to be used in other methods
|
|
3612
|
+
*/
|
|
3613
|
+
withSchema(schema) {
|
|
3614
|
+
this.schema = schema;
|
|
3615
|
+
this.explodedSchema = [this.schema];
|
|
3616
|
+
return this;
|
|
3617
|
+
}
|
|
3618
|
+
/**
|
|
3619
|
+
* List all existing tables in the current schema/database
|
|
3620
|
+
*/
|
|
3621
|
+
async tables() {
|
|
3622
|
+
return (await this.knex.select("tablename").from("pg_catalog.pg_tables").whereIn("schemaname", this.explodedSchema)).map(({ tablename }) => tablename);
|
|
3623
|
+
}
|
|
3624
|
+
async tableInfo(table) {
|
|
3625
|
+
const query = this.knex.select("table_name", "table_schema", this.knex.select(this.knex.raw("obj_description(oid)")).from("pg_class").where({ relkind: "r" }).andWhere({ relname: "table_name" }).as("table_comment")).from("information_schema.tables").whereIn("table_schema", this.explodedSchema).andWhereRaw("\"table_catalog\" = current_database()").andWhere({ table_type: "BASE TABLE" }).orderBy("table_name", "asc");
|
|
3626
|
+
if (table) {
|
|
3627
|
+
const rawTable = await query.andWhere({ table_name: table }).limit(1).first();
|
|
3628
|
+
return {
|
|
3629
|
+
name: rawTable.table_name,
|
|
3630
|
+
schema: rawTable.table_schema,
|
|
3631
|
+
comment: rawTable.table_comment
|
|
3632
|
+
};
|
|
3633
|
+
}
|
|
3634
|
+
return (await query).map((rawTable) => {
|
|
3635
|
+
return {
|
|
3636
|
+
name: rawTable.table_name,
|
|
3637
|
+
schema: rawTable.table_schema,
|
|
3638
|
+
comment: rawTable.table_comment
|
|
3639
|
+
};
|
|
3640
|
+
});
|
|
3641
|
+
}
|
|
3642
|
+
/**
|
|
3643
|
+
* Check if a table exists in the current schema/database
|
|
3644
|
+
*/
|
|
3645
|
+
async hasTable(table) {
|
|
3646
|
+
const subquery = this.knex.select().from("information_schema.tables").whereIn("table_schema", this.explodedSchema).andWhere({ table_name: table });
|
|
3647
|
+
const record = await this.knex.select(this.knex.raw("exists (?)", [subquery])).first();
|
|
3648
|
+
return (record === null || record === void 0 ? void 0 : record.exists) || false;
|
|
3649
|
+
}
|
|
3650
|
+
/**
|
|
3651
|
+
* Get all the available columns in the current schema/database. Can be filtered to a specific table
|
|
3652
|
+
*/
|
|
3653
|
+
async columns(table) {
|
|
3654
|
+
const query = this.knex.select("table_name", "column_name").from("information_schema.columns").whereIn("table_schema", this.explodedSchema);
|
|
3655
|
+
if (table) query.andWhere({ table_name: table });
|
|
3656
|
+
return (await query).map(({ table_name, column_name }) => ({
|
|
3657
|
+
table: table_name,
|
|
3658
|
+
column: column_name
|
|
3659
|
+
}));
|
|
3660
|
+
}
|
|
3661
|
+
async columnInfo(table, column) {
|
|
3662
|
+
const { knex: knex$1 } = this;
|
|
3663
|
+
const bindings = [];
|
|
3664
|
+
if (table) bindings.push(table);
|
|
3665
|
+
if (column) bindings.push(column);
|
|
3666
|
+
const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
|
|
3667
|
+
const [columns, constraints] = await Promise.all([knex$1.raw(`
|
|
3668
|
+
SELECT *, CASE WHEN res.is_generated THEN (
|
|
3669
|
+
SELECT
|
|
3670
|
+
generation_expression
|
|
3671
|
+
FROM
|
|
3672
|
+
information_schema.columns
|
|
3673
|
+
WHERE
|
|
3674
|
+
table_schema = res.schema
|
|
3675
|
+
AND table_name = res.table
|
|
3676
|
+
AND column_name = res.name
|
|
3677
|
+
) ELSE NULL END AS generation_expression
|
|
3678
|
+
FROM (
|
|
3679
|
+
SELECT
|
|
3680
|
+
att.attname AS name,
|
|
3681
|
+
rel.relname AS table,
|
|
3682
|
+
rel.relnamespace::regnamespace::text AS schema,
|
|
3683
|
+
format_type(att.atttypid, null) AS data_type,
|
|
3684
|
+
NOT att.attnotnull AS is_nullable,
|
|
3685
|
+
CASE WHEN att.attgenerated = '' THEN pg_get_expr(ad.adbin, ad.adrelid) ELSE null END AS default_value,
|
|
3686
|
+
att.attgenerated = 's' AS is_generated,
|
|
3687
|
+
CASE
|
|
3688
|
+
WHEN att.atttypid IN (1042, 1043) THEN (att.atttypmod - 4)::int4
|
|
3689
|
+
WHEN att.atttypid IN (1560, 1562) THEN (att.atttypmod)::int4
|
|
3690
|
+
ELSE NULL
|
|
3691
|
+
END AS max_length,
|
|
3692
|
+
des.description AS comment,
|
|
3693
|
+
CASE att.atttypid
|
|
3694
|
+
WHEN 21 THEN 16
|
|
3695
|
+
WHEN 23 THEN 32
|
|
3696
|
+
WHEN 20 THEN 64
|
|
3697
|
+
WHEN 1700 THEN
|
|
3698
|
+
CASE WHEN atttypmod = -1 THEN NULL
|
|
3699
|
+
ELSE (((atttypmod - 4) >> 16) & 65535)::int4
|
|
3700
|
+
END
|
|
3701
|
+
WHEN 700 THEN 24
|
|
3702
|
+
WHEN 701 THEN 53
|
|
3703
|
+
ELSE NULL
|
|
3704
|
+
END AS numeric_precision,
|
|
3705
|
+
CASE
|
|
3706
|
+
WHEN atttypid IN (21, 23, 20) THEN 0
|
|
3707
|
+
WHEN atttypid = 1700 THEN
|
|
3708
|
+
CASE
|
|
3709
|
+
WHEN atttypmod = -1 THEN NULL
|
|
3710
|
+
ELSE ((atttypmod - 4) & 65535)::int4
|
|
3711
|
+
END
|
|
3712
|
+
ELSE null
|
|
3713
|
+
END AS numeric_scale
|
|
3714
|
+
FROM
|
|
3715
|
+
pg_attribute att
|
|
3716
|
+
LEFT JOIN pg_class rel ON att.attrelid = rel.oid
|
|
3717
|
+
LEFT JOIN pg_attrdef ad ON (att.attrelid, att.attnum) = (ad.adrelid, ad.adnum)
|
|
3718
|
+
LEFT JOIN pg_description des ON (att.attrelid, att.attnum) = (des.objoid, des.objsubid)
|
|
3719
|
+
WHERE
|
|
3720
|
+
rel.relnamespace IN (${schemaIn})
|
|
3721
|
+
${table ? "AND rel.relname = ?" : ""}
|
|
3722
|
+
${column ? "AND att.attname = ?" : ""}
|
|
3723
|
+
AND rel.relkind = 'r'
|
|
3724
|
+
AND att.attnum > 0
|
|
3725
|
+
AND NOT att.attisdropped
|
|
3726
|
+
ORDER BY rel.relname, att.attnum) res;
|
|
3727
|
+
`, bindings), knex$1.raw(`
|
|
3728
|
+
SELECT
|
|
3729
|
+
con.contype AS type,
|
|
3730
|
+
rel.relname AS table,
|
|
3731
|
+
att.attname AS column,
|
|
3732
|
+
frel.relnamespace::regnamespace::text AS foreign_key_schema,
|
|
3733
|
+
frel.relname AS foreign_key_table,
|
|
3734
|
+
fatt.attname AS foreign_key_column
|
|
3735
|
+
FROM
|
|
3736
|
+
pg_constraint con
|
|
3737
|
+
LEFT JOIN pg_class rel ON con.conrelid = rel.oid
|
|
3738
|
+
LEFT JOIN pg_class frel ON con.confrelid = frel.oid
|
|
3739
|
+
LEFT JOIN pg_attribute att ON att.attrelid = con.conrelid AND att.attnum = con.conkey[1]
|
|
3740
|
+
LEFT JOIN pg_attribute fatt ON fatt.attrelid = con.confrelid AND fatt.attnum = con.confkey[1]
|
|
3741
|
+
WHERE con.connamespace IN (${schemaIn})
|
|
3742
|
+
AND array_length(con.conkey, 1) <= 1
|
|
3743
|
+
AND (con.confkey IS NULL OR array_length(con.confkey, 1) = 1)
|
|
3744
|
+
${table ? "AND rel.relname = ?" : ""}
|
|
3745
|
+
${column ? "AND att.attname = ?" : ""}
|
|
3746
|
+
`, bindings)]);
|
|
3747
|
+
const parsedColumms = columns.rows.map((col) => {
|
|
3748
|
+
var _col$default_value;
|
|
3749
|
+
const constraintsForColumn = constraints.rows.filter((constraint) => constraint.table === col.table && constraint.column === col.name);
|
|
3750
|
+
const foreignKeyConstraint = constraintsForColumn.find((constraint) => constraint.type === "f");
|
|
3751
|
+
return {
|
|
3752
|
+
...col,
|
|
3753
|
+
is_unique: constraintsForColumn.some((constraint) => ["u", "p"].includes(constraint.type)),
|
|
3754
|
+
is_primary_key: constraintsForColumn.some((constraint) => constraint.type === "p"),
|
|
3755
|
+
has_auto_increment: ["integer", "bigint"].includes(col.data_type) && (((_col$default_value = col.default_value) === null || _col$default_value === void 0 ? void 0 : _col$default_value.startsWith("nextval(")) ?? false),
|
|
3756
|
+
default_value: parseDefaultValue$5(col.default_value),
|
|
3757
|
+
foreign_key_schema: (foreignKeyConstraint === null || foreignKeyConstraint === void 0 ? void 0 : foreignKeyConstraint.foreign_key_schema) ?? null,
|
|
3758
|
+
foreign_key_table: (foreignKeyConstraint === null || foreignKeyConstraint === void 0 ? void 0 : foreignKeyConstraint.foreign_key_table) ?? null,
|
|
3759
|
+
foreign_key_column: (foreignKeyConstraint === null || foreignKeyConstraint === void 0 ? void 0 : foreignKeyConstraint.foreign_key_column) ?? null
|
|
3760
|
+
};
|
|
3761
|
+
});
|
|
3762
|
+
if (table && column) return parsedColumms[0];
|
|
3763
|
+
return parsedColumms;
|
|
3764
|
+
}
|
|
3765
|
+
/**
|
|
3766
|
+
* Check if the given table contains the given column
|
|
3767
|
+
*/
|
|
3768
|
+
async hasColumn(table, column) {
|
|
3769
|
+
const subquery = this.knex.select().from("information_schema.columns").whereIn("table_schema", this.explodedSchema).andWhere({
|
|
3770
|
+
table_name: table,
|
|
3771
|
+
column_name: column
|
|
3772
|
+
});
|
|
3773
|
+
const record = await this.knex.select(this.knex.raw("exists (?)", [subquery])).first();
|
|
3774
|
+
return (record === null || record === void 0 ? void 0 : record.exists) || false;
|
|
3775
|
+
}
|
|
3776
|
+
/**
|
|
3777
|
+
* Get the primary key column for the given table
|
|
3778
|
+
*/
|
|
3779
|
+
async primary(table) {
|
|
3780
|
+
const result = await this.knex.select("information_schema.key_column_usage.column_name").from("information_schema.key_column_usage").leftJoin("information_schema.table_constraints", function() {
|
|
3781
|
+
this.on("information_schema.table_constraints.constraint_name", "=", "information_schema.key_column_usage.constraint_name").andOn("information_schema.table_constraints.table_name", "=", "information_schema.key_column_usage.table_name");
|
|
3782
|
+
}).whereIn("information_schema.table_constraints.table_schema", this.explodedSchema).andWhere({
|
|
3783
|
+
"information_schema.table_constraints.constraint_type": "PRIMARY KEY",
|
|
3784
|
+
"information_schema.table_constraints.table_name": table
|
|
3785
|
+
});
|
|
3786
|
+
return result.length > 0 ? result.length === 1 ? result[0].column_name : result.map((r) => r.column_name) : null;
|
|
3787
|
+
}
|
|
3788
|
+
async foreignKeys(table) {
|
|
3789
|
+
const rowsWithoutQuotes = (await this.knex.raw(`
|
|
3790
|
+
SELECT
|
|
3791
|
+
c.conrelid::regclass::text AS "table",
|
|
3792
|
+
(
|
|
3793
|
+
SELECT
|
|
3794
|
+
STRING_AGG(a.attname, ','
|
|
3795
|
+
ORDER BY
|
|
3796
|
+
t.seq)
|
|
3797
|
+
FROM (
|
|
3798
|
+
SELECT
|
|
3799
|
+
ROW_NUMBER() OVER (ROWS UNBOUNDED PRECEDING) AS seq,
|
|
3800
|
+
attnum
|
|
3801
|
+
FROM
|
|
3802
|
+
UNNEST(c.conkey) AS t (attnum)) AS t
|
|
3803
|
+
INNER JOIN pg_attribute AS a ON a.attrelid = c.conrelid
|
|
3804
|
+
AND a.attnum = t.attnum) AS "column",
|
|
3805
|
+
tt.name AS foreign_key_table,
|
|
3806
|
+
(
|
|
3807
|
+
SELECT
|
|
3808
|
+
STRING_AGG(QUOTE_IDENT(a.attname), ','
|
|
3809
|
+
ORDER BY
|
|
3810
|
+
t.seq)
|
|
3811
|
+
FROM (
|
|
3812
|
+
SELECT
|
|
3813
|
+
ROW_NUMBER() OVER (ROWS UNBOUNDED PRECEDING) AS seq,
|
|
3814
|
+
attnum
|
|
3815
|
+
FROM
|
|
3816
|
+
UNNEST(c.confkey) AS t (attnum)) AS t
|
|
3817
|
+
INNER JOIN pg_attribute AS a ON a.attrelid = c.confrelid
|
|
3818
|
+
AND a.attnum = t.attnum) AS foreign_key_column,
|
|
3819
|
+
tt.schema AS foreign_key_schema,
|
|
3820
|
+
c.conname AS constraint_name,
|
|
3821
|
+
CASE confupdtype
|
|
3822
|
+
WHEN 'r' THEN
|
|
3823
|
+
'RESTRICT'
|
|
3824
|
+
WHEN 'c' THEN
|
|
3825
|
+
'CASCADE'
|
|
3826
|
+
WHEN 'n' THEN
|
|
3827
|
+
'SET NULL'
|
|
3828
|
+
WHEN 'd' THEN
|
|
3829
|
+
'SET DEFAULT'
|
|
3830
|
+
WHEN 'a' THEN
|
|
3831
|
+
'NO ACTION'
|
|
3832
|
+
ELSE
|
|
3833
|
+
NULL
|
|
3834
|
+
END AS on_update,
|
|
3835
|
+
CASE confdeltype
|
|
3836
|
+
WHEN 'r' THEN
|
|
3837
|
+
'RESTRICT'
|
|
3838
|
+
WHEN 'c' THEN
|
|
3839
|
+
'CASCADE'
|
|
3840
|
+
WHEN 'n' THEN
|
|
3841
|
+
'SET NULL'
|
|
3842
|
+
WHEN 'd' THEN
|
|
3843
|
+
'SET DEFAULT'
|
|
3844
|
+
WHEN 'a' THEN
|
|
3845
|
+
'NO ACTION'
|
|
3846
|
+
ELSE
|
|
3847
|
+
NULL
|
|
3848
|
+
END AS
|
|
3849
|
+
on_delete
|
|
3850
|
+
FROM
|
|
3851
|
+
pg_catalog.pg_constraint AS c
|
|
3852
|
+
INNER JOIN (
|
|
3853
|
+
SELECT
|
|
3854
|
+
pg_class.oid,
|
|
3855
|
+
QUOTE_IDENT(pg_namespace.nspname) AS SCHEMA,
|
|
3856
|
+
QUOTE_IDENT(pg_class.relname) AS name
|
|
3857
|
+
FROM
|
|
3858
|
+
pg_class
|
|
3859
|
+
INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid) AS tf ON tf.oid = c.conrelid
|
|
3860
|
+
INNER JOIN (
|
|
3861
|
+
SELECT
|
|
3862
|
+
pg_class.oid,
|
|
3863
|
+
QUOTE_IDENT(pg_namespace.nspname) AS SCHEMA,
|
|
3864
|
+
QUOTE_IDENT(pg_class.relname) AS name
|
|
3865
|
+
FROM
|
|
3866
|
+
pg_class
|
|
3867
|
+
INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid) AS tt ON tt.oid = c.confrelid
|
|
3868
|
+
WHERE
|
|
3869
|
+
c.contype = 'f';
|
|
3870
|
+
`)).rows.map(stripRowQuotes);
|
|
3871
|
+
if (table) return rowsWithoutQuotes.filter((row) => row.table === table);
|
|
3872
|
+
return rowsWithoutQuotes;
|
|
3873
|
+
function stripRowQuotes(row) {
|
|
3874
|
+
return Object.fromEntries(Object.entries(row).map(([key, value]) => {
|
|
3875
|
+
return [key, stripQuotes(value)];
|
|
3876
|
+
}));
|
|
3877
|
+
}
|
|
3878
|
+
}
|
|
3879
|
+
};
|
|
3880
|
+
|
|
3881
|
+
//#endregion
|
|
3882
|
+
//#region src/inspector/dialects/mssql.ts
|
|
3883
|
+
function rawColumnToColumn$2(rawColumn) {
|
|
3884
|
+
return {
|
|
3885
|
+
...rawColumn,
|
|
3886
|
+
default_value: parseDefaultValue$4(rawColumn.default_value),
|
|
3887
|
+
generation_expression: rawColumn.generation_expression || null,
|
|
3888
|
+
is_generated: !!rawColumn.is_generated,
|
|
3889
|
+
is_unique: rawColumn.is_unique === true,
|
|
3890
|
+
is_primary_key: rawColumn.is_primary_key === true,
|
|
3891
|
+
is_nullable: rawColumn.is_nullable === "YES",
|
|
3892
|
+
has_auto_increment: rawColumn.has_auto_increment === "YES",
|
|
3893
|
+
numeric_precision: rawColumn.numeric_precision || null,
|
|
3894
|
+
numeric_scale: rawColumn.numeric_scale || null,
|
|
3895
|
+
max_length: parseMaxLength(rawColumn)
|
|
3896
|
+
};
|
|
3897
|
+
function parseMaxLength(rawColumn$1) {
|
|
3898
|
+
const max_length = Number(rawColumn$1.max_length);
|
|
3899
|
+
if (Number.isNaN(max_length) || rawColumn$1.max_length === null || rawColumn$1.max_length === void 0) return null;
|
|
3900
|
+
if ([
|
|
3901
|
+
"nvarchar",
|
|
3902
|
+
"nchar",
|
|
3903
|
+
"ntext"
|
|
3904
|
+
].includes(rawColumn$1.data_type)) return max_length === -1 ? max_length : max_length / 2;
|
|
3905
|
+
return max_length;
|
|
3906
|
+
}
|
|
3907
|
+
}
|
|
3908
|
+
function parseDefaultValue$4(value) {
|
|
3909
|
+
if (value === null) return null;
|
|
3910
|
+
while (value.startsWith("(") && value.endsWith(")")) value = value.slice(1, -1);
|
|
3911
|
+
if (value.trim().toLowerCase() === "null") return null;
|
|
3912
|
+
return stripQuotes(value);
|
|
3913
|
+
}
|
|
3914
|
+
var MSSQL = class {
|
|
3915
|
+
knex;
|
|
3916
|
+
_schema;
|
|
3917
|
+
constructor(knex$1) {
|
|
3918
|
+
this.knex = knex$1;
|
|
3919
|
+
}
|
|
3920
|
+
/**
|
|
3921
|
+
* Set the schema to be used in other methods
|
|
3922
|
+
*/
|
|
3923
|
+
withSchema(schema) {
|
|
3924
|
+
this.schema = schema;
|
|
3925
|
+
return this;
|
|
3926
|
+
}
|
|
3927
|
+
get schema() {
|
|
3928
|
+
return this._schema || "dbo";
|
|
3929
|
+
}
|
|
3930
|
+
set schema(value) {
|
|
3931
|
+
this._schema = value;
|
|
3932
|
+
}
|
|
3933
|
+
/**
|
|
3934
|
+
* List all existing tables in the current schema/database
|
|
3935
|
+
*/
|
|
3936
|
+
async tables() {
|
|
3937
|
+
return (await this.knex.select("TABLE_NAME").from("INFORMATION_SCHEMA.TABLES").where({
|
|
3938
|
+
TABLE_TYPE: "BASE TABLE",
|
|
3939
|
+
TABLE_CATALOG: this.knex.client.database(),
|
|
3940
|
+
TABLE_SCHEMA: this.schema
|
|
3941
|
+
})).map(({ TABLE_NAME }) => TABLE_NAME);
|
|
3942
|
+
}
|
|
3943
|
+
async tableInfo(table) {
|
|
3944
|
+
const query = this.knex.select("TABLE_NAME", "TABLE_SCHEMA", "TABLE_CATALOG", "TABLE_TYPE").from("INFORMATION_SCHEMA.TABLES").where({
|
|
3945
|
+
TABLE_CATALOG: this.knex.client.database(),
|
|
3946
|
+
TABLE_TYPE: "BASE TABLE",
|
|
3947
|
+
TABLE_SCHEMA: this.schema
|
|
3948
|
+
});
|
|
3949
|
+
if (table) {
|
|
3950
|
+
const rawTable = await query.andWhere({ table_name: table }).first();
|
|
3951
|
+
return {
|
|
3952
|
+
name: rawTable.TABLE_NAME,
|
|
3953
|
+
schema: rawTable.TABLE_SCHEMA,
|
|
3954
|
+
catalog: rawTable.TABLE_CATALOG
|
|
3955
|
+
};
|
|
3956
|
+
}
|
|
3957
|
+
return (await query).map((rawTable) => {
|
|
3958
|
+
return {
|
|
3959
|
+
name: rawTable.TABLE_NAME,
|
|
3960
|
+
schema: rawTable.TABLE_SCHEMA,
|
|
3961
|
+
catalog: rawTable.TABLE_CATALOG
|
|
3962
|
+
};
|
|
3963
|
+
});
|
|
3964
|
+
}
|
|
3965
|
+
/**
|
|
3966
|
+
* Check if a table exists in the current schema/database
|
|
3967
|
+
*/
|
|
3968
|
+
async hasTable(table) {
|
|
3969
|
+
const result = await this.knex.count({ count: "*" }).from("INFORMATION_SCHEMA.TABLES").where({
|
|
3970
|
+
TABLE_CATALOG: this.knex.client.database(),
|
|
3971
|
+
table_name: table,
|
|
3972
|
+
TABLE_SCHEMA: this.schema
|
|
3973
|
+
}).first();
|
|
3974
|
+
return result && result.count === 1 || false;
|
|
3975
|
+
}
|
|
3976
|
+
/**
|
|
3977
|
+
* Get all the available columns in the current schema/database. Can be filtered to a specific table
|
|
3978
|
+
*/
|
|
3979
|
+
async columns(table) {
|
|
3980
|
+
const query = this.knex.select("TABLE_NAME", "COLUMN_NAME").from("INFORMATION_SCHEMA.COLUMNS").where({
|
|
3981
|
+
TABLE_CATALOG: this.knex.client.database(),
|
|
3982
|
+
TABLE_SCHEMA: this.schema
|
|
3983
|
+
});
|
|
3984
|
+
if (table) query.andWhere({ TABLE_NAME: table });
|
|
3985
|
+
return (await query).map(({ TABLE_NAME, COLUMN_NAME }) => ({
|
|
3986
|
+
table: TABLE_NAME,
|
|
3987
|
+
column: COLUMN_NAME
|
|
3988
|
+
}));
|
|
3989
|
+
}
|
|
3990
|
+
async columnInfo(table, column) {
|
|
3991
|
+
const dbName = this.knex.client.database();
|
|
3992
|
+
const query = this.knex.select(this.knex.raw(`
|
|
3993
|
+
[o].[name] AS [table],
|
|
3994
|
+
[c].[name] AS [name],
|
|
3995
|
+
[t].[name] AS [data_type],
|
|
3996
|
+
[c].[max_length] AS [max_length],
|
|
3997
|
+
[c].[precision] AS [numeric_precision],
|
|
3998
|
+
[c].[scale] AS [numeric_scale],
|
|
3999
|
+
CASE WHEN [c].[is_nullable] = 0 THEN
|
|
4000
|
+
'NO'
|
|
4001
|
+
ELSE
|
|
4002
|
+
'YES'
|
|
4003
|
+
END AS [is_nullable],
|
|
4004
|
+
object_definition ([c].[default_object_id]) AS [default_value],
|
|
4005
|
+
[i].[is_primary_key],
|
|
4006
|
+
[i].[is_unique],
|
|
4007
|
+
CASE [c].[is_identity]
|
|
4008
|
+
WHEN 1 THEN
|
|
4009
|
+
'YES'
|
|
4010
|
+
ELSE
|
|
4011
|
+
'NO'
|
|
4012
|
+
END AS [has_auto_increment],
|
|
4013
|
+
OBJECT_NAME ([fk].[referenced_object_id]) AS [foreign_key_table],
|
|
4014
|
+
COL_NAME ([fk].[referenced_object_id],
|
|
4015
|
+
[fk].[referenced_column_id]) AS [foreign_key_column],
|
|
4016
|
+
[cc].[is_computed] as [is_generated],
|
|
4017
|
+
[cc].[definition] as [generation_expression]`)).from(this.knex.raw("??.[sys].[columns] [c]", [dbName])).joinRaw("JOIN [sys].[types] [t] ON [c].[user_type_id] = [t].[user_type_id]").joinRaw("JOIN [sys].[tables] [o] ON [o].[object_id] = [c].[object_id]").joinRaw("JOIN [sys].[schemas] [s] ON [s].[schema_id] = [o].[schema_id]").joinRaw("LEFT JOIN [sys].[computed_columns] AS [cc] ON [cc].[object_id] = [c].[object_id] AND [cc].[column_id] = [c].[column_id]").joinRaw("LEFT JOIN [sys].[foreign_key_columns] AS [fk] ON [fk].[parent_object_id] = [c].[object_id] AND [fk].[parent_column_id] = [c].[column_id]").joinRaw(`LEFT JOIN (
|
|
4018
|
+
SELECT
|
|
4019
|
+
[ic].[object_id],
|
|
4020
|
+
[ic].[column_id],
|
|
4021
|
+
[ix].[is_unique],
|
|
4022
|
+
[ix].[is_primary_key],
|
|
4023
|
+
MAX([ic].[index_column_id]) OVER(partition by [ic].[index_id], [ic].[object_id]) AS index_column_count,
|
|
4024
|
+
ROW_NUMBER() OVER (
|
|
4025
|
+
PARTITION BY [ic].[object_id], [ic].[column_id]
|
|
4026
|
+
ORDER BY [ix].[is_primary_key] DESC, [ix].[is_unique] DESC
|
|
4027
|
+
) AS index_priority
|
|
4028
|
+
FROM
|
|
4029
|
+
[sys].[index_columns] [ic]
|
|
4030
|
+
JOIN [sys].[indexes] AS [ix] ON [ix].[object_id] = [ic].[object_id]
|
|
4031
|
+
AND [ix].[index_id] = [ic].[index_id]
|
|
4032
|
+
) AS [i]
|
|
4033
|
+
ON [i].[object_id] = [c].[object_id]
|
|
4034
|
+
AND [i].[column_id] = [c].[column_id]
|
|
4035
|
+
AND ISNULL([i].[index_column_count], 1) = 1
|
|
4036
|
+
AND ISNULL([i].[index_priority], 1) = 1`).where({ "s.name": this.schema });
|
|
4037
|
+
if (table) query.andWhere({ "o.name": table });
|
|
4038
|
+
if (column) {
|
|
4039
|
+
const rawColumn = await query.andWhere({ "c.name": column }).first();
|
|
4040
|
+
return rawColumnToColumn$2(rawColumn);
|
|
4041
|
+
}
|
|
4042
|
+
return (await query).map(rawColumnToColumn$2);
|
|
4043
|
+
}
|
|
4044
|
+
/**
|
|
4045
|
+
* Check if a table exists in the current schema/database
|
|
4046
|
+
*/
|
|
4047
|
+
async hasColumn(table, column) {
|
|
4048
|
+
const result = await this.knex.count({ count: "*" }).from("INFORMATION_SCHEMA.COLUMNS").where({
|
|
4049
|
+
TABLE_CATALOG: this.knex.client.database(),
|
|
4050
|
+
TABLE_NAME: table,
|
|
4051
|
+
COLUMN_NAME: column,
|
|
4052
|
+
TABLE_SCHEMA: this.schema
|
|
4053
|
+
}).first();
|
|
4054
|
+
return result && result.count === 1 || false;
|
|
4055
|
+
}
|
|
4056
|
+
/**
|
|
4057
|
+
* Get the primary key column for the given table
|
|
4058
|
+
*/
|
|
4059
|
+
async primary(table) {
|
|
4060
|
+
const results = await this.knex.raw(`SELECT
|
|
4061
|
+
Col.Column_Name
|
|
4062
|
+
FROM
|
|
4063
|
+
INFORMATION_SCHEMA.TABLE_CONSTRAINTS Tab,
|
|
4064
|
+
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE Col
|
|
4065
|
+
WHERE
|
|
4066
|
+
Col.Constraint_Name = Tab.Constraint_Name
|
|
4067
|
+
AND Col.Table_Name = Tab.Table_Name
|
|
4068
|
+
AND Constraint_Type = 'PRIMARY KEY'
|
|
4069
|
+
AND Col.Table_Name = ?
|
|
4070
|
+
AND Tab.CONSTRAINT_SCHEMA = ?`, [table, this.schema]);
|
|
4071
|
+
return results.length > 0 ? results.length === 1 ? results[0]["Column_Name"] : results.map((row) => row["Column_Name"]) : null;
|
|
4072
|
+
}
|
|
4073
|
+
async foreignKeys(table) {
|
|
4074
|
+
const result = await this.knex.raw(`
|
|
4075
|
+
SELECT
|
|
4076
|
+
OBJECT_NAME (fc.parent_object_id) AS "table",
|
|
4077
|
+
COL_NAME (fc.parent_object_id, fc.parent_column_id) AS "column",
|
|
4078
|
+
OBJECT_SCHEMA_NAME (f.referenced_object_id) AS foreign_key_schema,
|
|
4079
|
+
OBJECT_NAME (f.referenced_object_id) AS foreign_key_table,
|
|
4080
|
+
COL_NAME (fc.referenced_object_id, fc.referenced_column_id) AS foreign_key_column,
|
|
4081
|
+
f.name AS constraint_name,
|
|
4082
|
+
REPLACE(f.update_referential_action_desc, '_', ' ') AS on_update,
|
|
4083
|
+
REPLACE(f.delete_referential_action_desc, '_', ' ') AS on_delete
|
|
4084
|
+
FROM
|
|
4085
|
+
sys.foreign_keys AS f
|
|
4086
|
+
INNER JOIN sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id
|
|
4087
|
+
WHERE
|
|
4088
|
+
OBJECT_SCHEMA_NAME (f.parent_object_id) = ?;
|
|
4089
|
+
`, [this.schema]);
|
|
4090
|
+
if (table) return result === null || result === void 0 ? void 0 : result.filter((row) => row.table === table);
|
|
4091
|
+
return result;
|
|
4092
|
+
}
|
|
4093
|
+
};
|
|
4094
|
+
|
|
4095
|
+
//#endregion
|
|
4096
|
+
//#region src/inspector/dialects/mysql.ts
|
|
4097
|
+
function rawColumnToColumn$1(rawColumn) {
|
|
4098
|
+
var _rawColumn$EXTRA;
|
|
4099
|
+
let dataType = rawColumn.COLUMN_TYPE.replace(/\(.*?\)/, "");
|
|
4100
|
+
if (rawColumn.COLUMN_TYPE.startsWith("tinyint(1)")) dataType = "boolean";
|
|
4101
|
+
return {
|
|
4102
|
+
name: rawColumn.COLUMN_NAME,
|
|
4103
|
+
table: rawColumn.TABLE_NAME,
|
|
4104
|
+
collation: rawColumn.COLLATION_NAME,
|
|
4105
|
+
data_type: dataType,
|
|
4106
|
+
default_value: parseDefaultValue$3(rawColumn.COLUMN_DEFAULT),
|
|
4107
|
+
generation_expression: rawColumn.GENERATION_EXPRESSION || null,
|
|
4108
|
+
max_length: rawColumn.CHARACTER_MAXIMUM_LENGTH,
|
|
4109
|
+
numeric_precision: rawColumn.NUMERIC_PRECISION,
|
|
4110
|
+
numeric_scale: rawColumn.NUMERIC_SCALE,
|
|
4111
|
+
is_generated: !!((_rawColumn$EXTRA = rawColumn.EXTRA) === null || _rawColumn$EXTRA === void 0 ? void 0 : _rawColumn$EXTRA.endsWith("GENERATED")),
|
|
4112
|
+
is_nullable: rawColumn.IS_NULLABLE === "YES",
|
|
4113
|
+
is_unique: rawColumn.COLUMN_KEY === "UNI",
|
|
4114
|
+
is_primary_key: rawColumn.CONSTRAINT_NAME === "PRIMARY" || rawColumn.COLUMN_KEY === "PRI",
|
|
4115
|
+
has_auto_increment: rawColumn.EXTRA === "auto_increment",
|
|
4116
|
+
foreign_key_column: rawColumn.REFERENCED_COLUMN_NAME,
|
|
4117
|
+
foreign_key_table: rawColumn.REFERENCED_TABLE_NAME,
|
|
4118
|
+
comment: rawColumn.COLUMN_COMMENT
|
|
4119
|
+
};
|
|
4120
|
+
}
|
|
4121
|
+
function parseDefaultValue$3(value) {
|
|
4122
|
+
if (value === null || value.trim().toLowerCase() === "null") return null;
|
|
4123
|
+
return stripQuotes(value);
|
|
4124
|
+
}
|
|
4125
|
+
var MySQL = class {
|
|
4126
|
+
knex;
|
|
4127
|
+
constructor(knex$1) {
|
|
4128
|
+
this.knex = knex$1;
|
|
4129
|
+
}
|
|
4130
|
+
/**
|
|
4131
|
+
* List all existing tables in the current schema/database
|
|
4132
|
+
*/
|
|
4133
|
+
async tables() {
|
|
4134
|
+
return (await this.knex.select("TABLE_NAME").from("INFORMATION_SCHEMA.TABLES").where({
|
|
4135
|
+
TABLE_TYPE: "BASE TABLE",
|
|
4136
|
+
TABLE_SCHEMA: this.knex.client.database()
|
|
4137
|
+
})).map(({ TABLE_NAME }) => TABLE_NAME);
|
|
4138
|
+
}
|
|
4139
|
+
async tableInfo(table) {
|
|
4140
|
+
const query = this.knex.select("TABLE_NAME", "ENGINE", "TABLE_SCHEMA", "TABLE_COLLATION", "TABLE_COMMENT").from("information_schema.tables").where({
|
|
4141
|
+
table_schema: this.knex.client.database(),
|
|
4142
|
+
table_type: "BASE TABLE"
|
|
4143
|
+
});
|
|
4144
|
+
if (table) {
|
|
4145
|
+
const rawTable = await query.andWhere({ table_name: table }).first();
|
|
4146
|
+
return {
|
|
4147
|
+
name: rawTable.TABLE_NAME,
|
|
4148
|
+
schema: rawTable.TABLE_SCHEMA,
|
|
4149
|
+
comment: rawTable.TABLE_COMMENT,
|
|
4150
|
+
collation: rawTable.TABLE_COLLATION,
|
|
4151
|
+
engine: rawTable.ENGINE
|
|
4152
|
+
};
|
|
4153
|
+
}
|
|
4154
|
+
return (await query).map((rawTable) => {
|
|
4155
|
+
return {
|
|
4156
|
+
name: rawTable.TABLE_NAME,
|
|
4157
|
+
schema: rawTable.TABLE_SCHEMA,
|
|
4158
|
+
comment: rawTable.TABLE_COMMENT,
|
|
4159
|
+
collation: rawTable.TABLE_COLLATION,
|
|
4160
|
+
engine: rawTable.ENGINE
|
|
4161
|
+
};
|
|
4162
|
+
});
|
|
4163
|
+
}
|
|
4164
|
+
/**
|
|
4165
|
+
* Check if a table exists in the current schema/database
|
|
4166
|
+
*/
|
|
4167
|
+
async hasTable(table) {
|
|
4168
|
+
const result = await this.knex.count({ count: "*" }).from("information_schema.tables").where({
|
|
4169
|
+
table_schema: this.knex.client.database(),
|
|
4170
|
+
table_name: table
|
|
4171
|
+
}).first();
|
|
4172
|
+
return result && result.count === 1 || false;
|
|
4173
|
+
}
|
|
4174
|
+
/**
|
|
4175
|
+
* Get all the available columns in the current schema/database. Can be filtered to a specific table
|
|
4176
|
+
*/
|
|
4177
|
+
async columns(table) {
|
|
4178
|
+
const query = this.knex.select("TABLE_NAME", "COLUMN_NAME").from("INFORMATION_SCHEMA.COLUMNS").where({ TABLE_SCHEMA: this.knex.client.database() });
|
|
4179
|
+
if (table) query.andWhere({ TABLE_NAME: table });
|
|
4180
|
+
return (await query).map(({ TABLE_NAME, COLUMN_NAME }) => ({
|
|
4181
|
+
table: TABLE_NAME,
|
|
4182
|
+
column: COLUMN_NAME
|
|
4183
|
+
}));
|
|
4184
|
+
}
|
|
4185
|
+
async columnInfo(table, column) {
|
|
4186
|
+
const query = this.knex.select("c.TABLE_NAME", "c.COLUMN_NAME", "c.COLUMN_DEFAULT", "c.COLUMN_TYPE", "c.CHARACTER_MAXIMUM_LENGTH", "c.IS_NULLABLE", "c.COLUMN_KEY", "c.EXTRA", "c.COLLATION_NAME", "c.COLUMN_COMMENT", "c.NUMERIC_PRECISION", "c.NUMERIC_SCALE", "c.GENERATION_EXPRESSION", "fk.REFERENCED_TABLE_NAME", "fk.REFERENCED_COLUMN_NAME", "fk.CONSTRAINT_NAME", "rc.UPDATE_RULE", "rc.DELETE_RULE", "rc.MATCH_OPTION").from("INFORMATION_SCHEMA.COLUMNS as c").leftJoin("INFORMATION_SCHEMA.KEY_COLUMN_USAGE as fk", function() {
|
|
4187
|
+
this.on("c.TABLE_NAME", "=", "fk.TABLE_NAME").andOn("fk.COLUMN_NAME", "=", "c.COLUMN_NAME").andOn("fk.CONSTRAINT_SCHEMA", "=", "c.TABLE_SCHEMA");
|
|
4188
|
+
}).leftJoin("INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as rc", function() {
|
|
4189
|
+
this.on("rc.TABLE_NAME", "=", "fk.TABLE_NAME").andOn("rc.CONSTRAINT_NAME", "=", "fk.CONSTRAINT_NAME").andOn("rc.CONSTRAINT_SCHEMA", "=", "fk.CONSTRAINT_SCHEMA");
|
|
4190
|
+
}).where({ "c.TABLE_SCHEMA": this.knex.client.database() });
|
|
4191
|
+
if (table) query.andWhere({ "c.TABLE_NAME": table });
|
|
4192
|
+
if (column) {
|
|
4193
|
+
const rawColumn = await query.andWhere({ "c.column_name": column }).first();
|
|
4194
|
+
return rawColumnToColumn$1(rawColumn);
|
|
4195
|
+
}
|
|
4196
|
+
return (await query).map(rawColumnToColumn$1).sort((column$1) => +!column$1.foreign_key_column).filter((column$1, index, records) => {
|
|
4197
|
+
return records.findIndex((_column) => {
|
|
4198
|
+
return column$1.name === _column.name && column$1.table === _column.table;
|
|
4199
|
+
}) === index;
|
|
4200
|
+
});
|
|
4201
|
+
}
|
|
4202
|
+
/**
|
|
4203
|
+
* Check if a table exists in the current schema/database
|
|
4204
|
+
*/
|
|
4205
|
+
async hasColumn(table, column) {
|
|
4206
|
+
const result = await this.knex.count("*", { as: "count" }).from("information_schema.columns").where({
|
|
4207
|
+
table_schema: this.knex.client.database(),
|
|
4208
|
+
table_name: table,
|
|
4209
|
+
column_name: column
|
|
4210
|
+
}).first();
|
|
4211
|
+
return !!(result && result.count);
|
|
4212
|
+
}
|
|
4213
|
+
/**
|
|
4214
|
+
* Get the primary key column for the given table
|
|
4215
|
+
*/
|
|
4216
|
+
async primary(table) {
|
|
4217
|
+
const results = await this.knex.raw("SHOW KEYS FROM ?? WHERE Key_name = 'PRIMARY'", table);
|
|
4218
|
+
if (results && results.length && results[0].length) {
|
|
4219
|
+
if (results[0].length === 1) return results[0][0]["Column_name"];
|
|
4220
|
+
return results[0].map((row) => row["Column_name"]);
|
|
4221
|
+
}
|
|
4222
|
+
return null;
|
|
4223
|
+
}
|
|
4224
|
+
async foreignKeys(table) {
|
|
4225
|
+
const query = this.knex.select("rc.TABLE_NAME AS table", "kcu.COLUMN_NAME AS column", "rc.REFERENCED_TABLE_NAME AS foreign_key_table", "kcu.REFERENCED_COLUMN_NAME AS foreign_key_column", "rc.CONSTRAINT_NAME AS constraint_name", "rc.UPDATE_RULE AS on_update", "rc.DELETE_RULE AS on_delete").from("information_schema.referential_constraints AS rc").leftJoin("information_schema.key_column_usage AS kcu ", function() {
|
|
4226
|
+
this.on("rc.CONSTRAINT_NAME", "=", "kcu.CONSTRAINT_NAME").andOn("kcu.CONSTRAINT_SCHEMA", "=", "rc.CONSTRAINT_SCHEMA");
|
|
4227
|
+
}).where({ "rc.CONSTRAINT_SCHEMA": this.knex.client.database() });
|
|
4228
|
+
if (table) query.andWhere({ "rc.TABLE_NAME": table });
|
|
4229
|
+
return await query;
|
|
4230
|
+
}
|
|
4231
|
+
async uniqueConstraints(table) {
|
|
4232
|
+
const { knex: knex$1 } = this;
|
|
4233
|
+
const query = knex$1.select("stat.table_name AS table_name", "stat.index_name AS constraint_name", knex$1.raw("group_concat(stat.column_name ORDER BY stat.seq_in_index separator ', ') AS columns")).from("information_schema.statistics stat").join("information_schema.table_constraints tco", function() {
|
|
4234
|
+
this.on("stat.table_schema", "=", "tco.table_schema").andOn("stat.table_name", "=", "tco.table_name").andOn("stat.index_name", "=", "tco.constraint_name");
|
|
4235
|
+
}).where("stat.non_unique", "=", 0).andWhere("tco.constraint_type", "=", "UNIQUE").andWhere("stat.table_schema", knex$1.client.database()).groupBy([
|
|
4236
|
+
"stat.table_name",
|
|
4237
|
+
"stat.index_name",
|
|
4238
|
+
"tco.constraint_type"
|
|
4239
|
+
]);
|
|
4240
|
+
if (table) query.andWhere("stat.table_name", "=", table);
|
|
4241
|
+
return (await query).map((v) => ({
|
|
4242
|
+
table: v.table_name,
|
|
4243
|
+
constraint_name: v.constraint_name,
|
|
4244
|
+
columns: v.columns
|
|
4245
|
+
}));
|
|
4246
|
+
}
|
|
4247
|
+
};
|
|
4248
|
+
|
|
4249
|
+
//#endregion
|
|
4250
|
+
//#region src/inspector/dialects/oracledb.ts
|
|
4251
|
+
/**
|
|
4252
|
+
* NOTE: Use previous optimizer for better data dictionary performance.
|
|
4253
|
+
*/
|
|
4254
|
+
const OPTIMIZER_FEATURES = "11.2.0.4";
|
|
4255
|
+
function rawColumnToColumn(rawColumn) {
|
|
4256
|
+
const is_generated = rawColumn.VIRTUAL_COLUMN === "YES";
|
|
4257
|
+
const default_value = parseDefaultValue$2(rawColumn.DATA_DEFAULT);
|
|
4258
|
+
return {
|
|
4259
|
+
name: rawColumn.COLUMN_NAME,
|
|
4260
|
+
table: rawColumn.TABLE_NAME,
|
|
4261
|
+
data_type: rawColumn.DATA_TYPE,
|
|
4262
|
+
default_value: !is_generated ? default_value : null,
|
|
4263
|
+
generation_expression: is_generated ? default_value : null,
|
|
4264
|
+
max_length: rawColumn.DATA_LENGTH,
|
|
4265
|
+
numeric_precision: rawColumn.DATA_PRECISION,
|
|
4266
|
+
numeric_scale: rawColumn.DATA_SCALE,
|
|
4267
|
+
is_generated: rawColumn.VIRTUAL_COLUMN === "YES",
|
|
4268
|
+
is_nullable: rawColumn.NULLABLE === "Y",
|
|
4269
|
+
is_unique: rawColumn.CONSTRAINT_TYPE === "U",
|
|
4270
|
+
is_primary_key: rawColumn.CONSTRAINT_TYPE === "P",
|
|
4271
|
+
has_auto_increment: rawColumn.IDENTITY_COLUMN === "YES",
|
|
4272
|
+
foreign_key_column: rawColumn.REFERENCED_COLUMN_NAME,
|
|
4273
|
+
foreign_key_table: rawColumn.REFERENCED_TABLE_NAME,
|
|
4274
|
+
comment: rawColumn.COLUMN_COMMENT
|
|
4275
|
+
};
|
|
4276
|
+
}
|
|
4277
|
+
function parseDefaultValue$2(value) {
|
|
4278
|
+
if (value === null || value.trim().toLowerCase() === "null") return null;
|
|
4279
|
+
if (value === "CURRENT_TIMESTAMP ") return "CURRENT_TIMESTAMP";
|
|
4280
|
+
return stripQuotes(value);
|
|
4281
|
+
}
|
|
4282
|
+
var oracleDB = class {
|
|
4283
|
+
knex;
|
|
4284
|
+
constructor(knex$1) {
|
|
4285
|
+
this.knex = knex$1;
|
|
4286
|
+
}
|
|
4287
|
+
/**
|
|
4288
|
+
* List all existing tables in the current schema/database
|
|
4289
|
+
*/
|
|
4290
|
+
async tables() {
|
|
4291
|
+
return (await this.knex.select(this.knex.raw(`
|
|
4292
|
+
/*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') */
|
|
4293
|
+
"TABLE_NAME" "name"
|
|
4294
|
+
`)).from("USER_TABLES")).map(({ name }) => name);
|
|
4295
|
+
}
|
|
4296
|
+
async tableInfo(table) {
|
|
4297
|
+
const query = this.knex.select(this.knex.raw(`
|
|
4298
|
+
/*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') */
|
|
4299
|
+
"TABLE_NAME" "name"
|
|
4300
|
+
`)).from("USER_TABLES");
|
|
4301
|
+
if (table) return await query.andWhere({ TABLE_NAME: table }).first();
|
|
4302
|
+
return await query;
|
|
4303
|
+
}
|
|
4304
|
+
/**
|
|
4305
|
+
* Check if a table exists in the current schema/database
|
|
4306
|
+
*/
|
|
4307
|
+
async hasTable(table) {
|
|
4308
|
+
const result = await this.knex.select(this.knex.raw(`
|
|
4309
|
+
/*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') */
|
|
4310
|
+
COUNT(*) "count"
|
|
4311
|
+
`)).from("USER_TABLES").where({ TABLE_NAME: table }).first();
|
|
4312
|
+
return !!(result === null || result === void 0 ? void 0 : result.count);
|
|
4313
|
+
}
|
|
4314
|
+
/**
|
|
4315
|
+
* Get all the available columns in the current schema/database. Can be filtered to a specific table
|
|
4316
|
+
*/
|
|
4317
|
+
async columns(table) {
|
|
4318
|
+
const query = this.knex.select(this.knex.raw(`
|
|
4319
|
+
/*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') NO_QUERY_TRANSFORMATION */
|
|
4320
|
+
"TABLE_NAME" "table",
|
|
4321
|
+
"COLUMN_NAME" "column"
|
|
4322
|
+
`)).from("USER_TAB_COLS").where({ HIDDEN_COLUMN: "NO" });
|
|
4323
|
+
if (table) query.andWhere({ TABLE_NAME: table });
|
|
4324
|
+
return await query;
|
|
4325
|
+
}
|
|
4326
|
+
async columnInfo(table, column) {
|
|
4327
|
+
/**
|
|
4328
|
+
* NOTE: Keep in mind, this query is optimized for speed.
|
|
4329
|
+
*/
|
|
4330
|
+
const query = this.knex.with("uc", this.knex.raw(`
|
|
4331
|
+
SELECT /*+ MATERIALIZE */
|
|
4332
|
+
"uc"."TABLE_NAME",
|
|
4333
|
+
"ucc"."COLUMN_NAME",
|
|
4334
|
+
"uc"."CONSTRAINT_NAME",
|
|
4335
|
+
"uc"."CONSTRAINT_TYPE",
|
|
4336
|
+
"uc"."R_CONSTRAINT_NAME",
|
|
4337
|
+
COUNT(*) OVER(
|
|
4338
|
+
PARTITION BY
|
|
4339
|
+
"uc"."CONSTRAINT_NAME"
|
|
4340
|
+
) "CONSTRAINT_COUNT",
|
|
4341
|
+
ROW_NUMBER() OVER(
|
|
4342
|
+
PARTITION BY
|
|
4343
|
+
"uc"."TABLE_NAME",
|
|
4344
|
+
"ucc"."COLUMN_NAME"
|
|
4345
|
+
ORDER BY
|
|
4346
|
+
"uc"."CONSTRAINT_TYPE"
|
|
4347
|
+
) "CONSTRAINT_PRIORITY"
|
|
4348
|
+
FROM "USER_CONSTRAINTS" "uc"
|
|
4349
|
+
INNER JOIN "USER_CONS_COLUMNS" "ucc"
|
|
4350
|
+
ON "uc"."CONSTRAINT_NAME" = "ucc"."CONSTRAINT_NAME"
|
|
4351
|
+
WHERE "uc"."CONSTRAINT_TYPE" IN ('P', 'U', 'R')
|
|
4352
|
+
`)).select(this.knex.raw(`
|
|
4353
|
+
/*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') */
|
|
4354
|
+
"c"."TABLE_NAME",
|
|
4355
|
+
"c"."COLUMN_NAME",
|
|
4356
|
+
"c"."DATA_DEFAULT",
|
|
4357
|
+
"c"."DATA_TYPE",
|
|
4358
|
+
"c"."DATA_LENGTH",
|
|
4359
|
+
"c"."DATA_PRECISION",
|
|
4360
|
+
"c"."DATA_SCALE",
|
|
4361
|
+
"c"."NULLABLE",
|
|
4362
|
+
"c"."IDENTITY_COLUMN",
|
|
4363
|
+
"c"."VIRTUAL_COLUMN",
|
|
4364
|
+
"cm"."COMMENTS" "COLUMN_COMMENT",
|
|
4365
|
+
"ct"."CONSTRAINT_TYPE",
|
|
4366
|
+
"fk"."TABLE_NAME" "REFERENCED_TABLE_NAME",
|
|
4367
|
+
"fk"."COLUMN_NAME" "REFERENCED_COLUMN_NAME"
|
|
4368
|
+
FROM "USER_TAB_COLS" "c"
|
|
4369
|
+
LEFT JOIN "USER_COL_COMMENTS" "cm"
|
|
4370
|
+
ON "c"."TABLE_NAME" = "cm"."TABLE_NAME"
|
|
4371
|
+
AND "c"."COLUMN_NAME" = "cm"."COLUMN_NAME"
|
|
4372
|
+
LEFT JOIN "uc" "ct"
|
|
4373
|
+
ON "c"."TABLE_NAME" = "ct"."TABLE_NAME"
|
|
4374
|
+
AND "c"."COLUMN_NAME" = "ct"."COLUMN_NAME"
|
|
4375
|
+
AND "ct"."CONSTRAINT_COUNT" = 1
|
|
4376
|
+
AND "ct"."CONSTRAINT_PRIORITY" = 1
|
|
4377
|
+
LEFT JOIN "uc" "fk"
|
|
4378
|
+
ON "ct"."R_CONSTRAINT_NAME" = "fk"."CONSTRAINT_NAME"
|
|
4379
|
+
`)).where({ "c.HIDDEN_COLUMN": "NO" });
|
|
4380
|
+
if (table) query.andWhere({ "c.TABLE_NAME": table });
|
|
4381
|
+
if (column) {
|
|
4382
|
+
const rawColumn = await query.andWhere({ "c.COLUMN_NAME": column }).first();
|
|
4383
|
+
return rawColumnToColumn(rawColumn);
|
|
4384
|
+
}
|
|
4385
|
+
return (await query).map(rawColumnToColumn);
|
|
4386
|
+
}
|
|
4387
|
+
/**
|
|
4388
|
+
* Check if a table exists in the current schema/database
|
|
4389
|
+
*/
|
|
4390
|
+
async hasColumn(table, column) {
|
|
4391
|
+
const result = await this.knex.select(this.knex.raw(`
|
|
4392
|
+
/*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') NO_QUERY_TRANSFORMATION */
|
|
4393
|
+
COUNT(*) "count"
|
|
4394
|
+
`)).from("USER_TAB_COLS").where({
|
|
4395
|
+
TABLE_NAME: table,
|
|
4396
|
+
COLUMN_NAME: column,
|
|
4397
|
+
HIDDEN_COLUMN: "NO"
|
|
4398
|
+
}).first();
|
|
4399
|
+
return !!(result === null || result === void 0 ? void 0 : result.count);
|
|
4400
|
+
}
|
|
4401
|
+
/**
|
|
4402
|
+
* Get the primary key column for the given table
|
|
4403
|
+
*/
|
|
4404
|
+
async primary(table) {
|
|
4405
|
+
/**
|
|
4406
|
+
* NOTE: Keep in mind, this query is optimized for speed.
|
|
4407
|
+
*/
|
|
4408
|
+
const result = await this.knex.with("uc", this.knex.select(this.knex.raw("/*+ MATERIALIZE */ \"CONSTRAINT_NAME\"")).from("USER_CONSTRAINTS").where({
|
|
4409
|
+
TABLE_NAME: table,
|
|
4410
|
+
CONSTRAINT_TYPE: "P"
|
|
4411
|
+
})).select(this.knex.raw(`
|
|
4412
|
+
/*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') */
|
|
4413
|
+
"ucc"."COLUMN_NAME"
|
|
4414
|
+
FROM "USER_CONS_COLUMNS" "ucc"
|
|
4415
|
+
INNER JOIN "uc" "pk"
|
|
4416
|
+
ON "ucc"."CONSTRAINT_NAME" = "pk"."CONSTRAINT_NAME"
|
|
4417
|
+
`));
|
|
4418
|
+
return result.length > 0 ? result.length === 1 ? result[0].COLUMN_NAME : result.map((r) => r.COLUMN_NAME) : null;
|
|
4419
|
+
}
|
|
4420
|
+
async foreignKeys(table) {
|
|
4421
|
+
/**
|
|
4422
|
+
* NOTE: Keep in mind, this query is optimized for speed.
|
|
4423
|
+
*/
|
|
4424
|
+
const query = this.knex.with("ucc", this.knex.raw(`
|
|
4425
|
+
SELECT /*+ MATERIALIZE */
|
|
4426
|
+
"TABLE_NAME",
|
|
4427
|
+
"COLUMN_NAME",
|
|
4428
|
+
"CONSTRAINT_NAME"
|
|
4429
|
+
FROM "USER_CONS_COLUMNS"
|
|
4430
|
+
`)).select(this.knex.raw(`
|
|
4431
|
+
/*+ OPTIMIZER_FEATURES_ENABLE('${OPTIMIZER_FEATURES}') */
|
|
4432
|
+
"uc"."TABLE_NAME" "table",
|
|
4433
|
+
"fcc"."COLUMN_NAME" "column",
|
|
4434
|
+
"rcc"."TABLE_NAME" AS "foreign_key_table",
|
|
4435
|
+
"rcc"."COLUMN_NAME" AS "foreign_key_column",
|
|
4436
|
+
"uc"."CONSTRAINT_NAME" "constraint_name",
|
|
4437
|
+
NULL as "on_update",
|
|
4438
|
+
"uc"."DELETE_RULE" "on_delete"
|
|
4439
|
+
FROM "USER_CONSTRAINTS" "uc"
|
|
4440
|
+
INNER JOIN "ucc" "fcc"
|
|
4441
|
+
ON "uc"."CONSTRAINT_NAME" = "fcc"."CONSTRAINT_NAME"
|
|
4442
|
+
INNER JOIN "ucc" "rcc"
|
|
4443
|
+
ON "uc"."R_CONSTRAINT_NAME" = "rcc"."CONSTRAINT_NAME"
|
|
4444
|
+
`)).where({ "uc.CONSTRAINT_TYPE": "R" });
|
|
4445
|
+
if (table) query.andWhere({ "uc.TABLE_NAME": table });
|
|
4446
|
+
return await query;
|
|
4447
|
+
}
|
|
4448
|
+
};
|
|
4449
|
+
|
|
4450
|
+
//#endregion
|
|
4451
|
+
//#region src/inspector/dialects/postgres.ts
|
|
4452
|
+
/**
|
|
4453
|
+
* Converts Postgres default value to JS
|
|
4454
|
+
* Eg `'example'::character varying` => `example`
|
|
4455
|
+
*/
|
|
4456
|
+
function parseDefaultValue$1(value) {
|
|
4457
|
+
if (value === null) return null;
|
|
4458
|
+
if (value.startsWith("nextval(")) return value;
|
|
4459
|
+
value = value.split("::")[0];
|
|
4460
|
+
if (value.trim().toLowerCase() === "null") return null;
|
|
4461
|
+
return stripQuotes(value);
|
|
4462
|
+
}
|
|
4463
|
+
var Postgres = class {
|
|
4464
|
+
knex;
|
|
4465
|
+
schema;
|
|
4466
|
+
explodedSchema;
|
|
4467
|
+
constructor(knex$1) {
|
|
4468
|
+
this.knex = knex$1;
|
|
4469
|
+
const config = knex$1.client.config;
|
|
4470
|
+
if (!config.searchPath) {
|
|
4471
|
+
this.schema = "public";
|
|
4472
|
+
this.explodedSchema = [this.schema];
|
|
4473
|
+
} else if (typeof config.searchPath === "string") {
|
|
4474
|
+
this.schema = config.searchPath;
|
|
4475
|
+
this.explodedSchema = [config.searchPath];
|
|
4476
|
+
} else {
|
|
4477
|
+
this.schema = config.searchPath[0];
|
|
4478
|
+
this.explodedSchema = config.searchPath;
|
|
4479
|
+
}
|
|
4480
|
+
}
|
|
4481
|
+
/**
|
|
4482
|
+
* Set the schema to be used in other methods
|
|
4483
|
+
*/
|
|
4484
|
+
withSchema(schema) {
|
|
4485
|
+
this.schema = schema;
|
|
4486
|
+
this.explodedSchema = [this.schema];
|
|
4487
|
+
return this;
|
|
4488
|
+
}
|
|
4489
|
+
/**
|
|
4490
|
+
* List all existing tables in the current schema/database
|
|
4491
|
+
*/
|
|
4492
|
+
async tables() {
|
|
4493
|
+
const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
|
|
4494
|
+
return (await this.knex.raw(`
|
|
4495
|
+
SELECT
|
|
4496
|
+
rel.relname AS name
|
|
4497
|
+
FROM
|
|
4498
|
+
pg_class rel
|
|
4499
|
+
WHERE
|
|
4500
|
+
rel.relnamespace IN (${schemaIn})
|
|
4501
|
+
AND rel.relkind = 'r'
|
|
4502
|
+
ORDER BY rel.relname
|
|
4503
|
+
`)).rows.map((row) => row.name);
|
|
4504
|
+
}
|
|
4505
|
+
async tableInfo(table) {
|
|
4506
|
+
const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
|
|
4507
|
+
const bindings = [];
|
|
4508
|
+
if (table) bindings.push(table);
|
|
4509
|
+
const result = await this.knex.raw(`
|
|
4510
|
+
SELECT
|
|
4511
|
+
rel.relnamespace::regnamespace::text AS schema,
|
|
4512
|
+
rel.relname AS name,
|
|
4513
|
+
des.description AS comment
|
|
4514
|
+
FROM
|
|
4515
|
+
pg_class rel
|
|
4516
|
+
LEFT JOIN pg_description des ON rel.oid = des.objoid AND des.objsubid = 0
|
|
4517
|
+
WHERE
|
|
4518
|
+
rel.relnamespace IN (${schemaIn})
|
|
4519
|
+
${table ? "AND rel.relname = ?" : ""}
|
|
4520
|
+
AND rel.relkind = 'r'
|
|
4521
|
+
ORDER BY rel.relname
|
|
4522
|
+
`, bindings);
|
|
4523
|
+
if (table) return result.rows[0];
|
|
4524
|
+
return result.rows;
|
|
4525
|
+
}
|
|
4526
|
+
/**
|
|
4527
|
+
* Check if a table exists in the current schema/database
|
|
4528
|
+
*/
|
|
4529
|
+
async hasTable(table) {
|
|
4530
|
+
const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
|
|
4531
|
+
return (await this.knex.raw(`
|
|
4532
|
+
SELECT
|
|
4533
|
+
rel.relname AS name
|
|
4534
|
+
FROM
|
|
4535
|
+
pg_class rel
|
|
4536
|
+
WHERE
|
|
4537
|
+
rel.relnamespace IN (${schemaIn})
|
|
4538
|
+
AND rel.relkind = 'r'
|
|
4539
|
+
AND rel.relname = ?
|
|
4540
|
+
ORDER BY rel.relname
|
|
4541
|
+
`, [table])).rows.length > 0;
|
|
4542
|
+
}
|
|
4543
|
+
/**
|
|
4544
|
+
* Get all the available columns in the current schema/database. Can be filtered to a specific table
|
|
4545
|
+
*/
|
|
4546
|
+
async columns(table) {
|
|
4547
|
+
const bindings = [];
|
|
4548
|
+
if (table) bindings.push(table);
|
|
4549
|
+
const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
|
|
4550
|
+
return (await this.knex.raw(`
|
|
4551
|
+
SELECT
|
|
4552
|
+
att.attname AS column,
|
|
4553
|
+
rel.relname AS table
|
|
4554
|
+
FROM
|
|
4555
|
+
pg_attribute att
|
|
4556
|
+
LEFT JOIN pg_class rel ON att.attrelid = rel.oid
|
|
4557
|
+
WHERE
|
|
4558
|
+
rel.relnamespace IN (${schemaIn})
|
|
4559
|
+
${table ? "AND rel.relname = ?" : ""}
|
|
4560
|
+
AND rel.relkind = 'r'
|
|
4561
|
+
AND att.attnum > 0
|
|
4562
|
+
AND NOT att.attisdropped;
|
|
4563
|
+
`, bindings)).rows;
|
|
4564
|
+
}
|
|
4565
|
+
async columnInfo(table, column) {
|
|
4566
|
+
var _versionResponse$rows;
|
|
4567
|
+
const { knex: knex$1 } = this;
|
|
4568
|
+
const bindings = [];
|
|
4569
|
+
if (table) bindings.push(table);
|
|
4570
|
+
if (column) bindings.push(column);
|
|
4571
|
+
const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
|
|
4572
|
+
const majorVersion = ((_versionResponse$rows = (await this.knex.raw("SHOW server_version")).rows) === null || _versionResponse$rows === void 0 || (_versionResponse$rows = _versionResponse$rows[0]) === null || _versionResponse$rows === void 0 || (_versionResponse$rows = _versionResponse$rows.server_version) === null || _versionResponse$rows === void 0 || (_versionResponse$rows = _versionResponse$rows.split(".")) === null || _versionResponse$rows === void 0 ? void 0 : _versionResponse$rows[0]) ?? 10;
|
|
4573
|
+
let generationSelect = `
|
|
4574
|
+
NULL AS generation_expression,
|
|
4575
|
+
pg_get_expr(ad.adbin, ad.adrelid) AS default_value,
|
|
4576
|
+
FALSE AS is_generated,
|
|
4577
|
+
`;
|
|
4578
|
+
if (Number(majorVersion) >= 12) generationSelect = `
|
|
4579
|
+
CASE WHEN att.attgenerated = 's' THEN pg_get_expr(ad.adbin, ad.adrelid) ELSE null END AS generation_expression,
|
|
4580
|
+
CASE WHEN att.attgenerated = '' THEN pg_get_expr(ad.adbin, ad.adrelid) ELSE null END AS default_value,
|
|
4581
|
+
att.attgenerated = 's' AS is_generated,
|
|
4582
|
+
`;
|
|
4583
|
+
const [columns, constraints] = await Promise.all([knex$1.raw(`
|
|
4584
|
+
SELECT
|
|
4585
|
+
att.attname AS name,
|
|
4586
|
+
rel.relname AS table,
|
|
4587
|
+
rel.relnamespace::regnamespace::text as schema,
|
|
4588
|
+
att.atttypid::regtype::text AS data_type,
|
|
4589
|
+
NOT att.attnotnull AS is_nullable,
|
|
4590
|
+
${generationSelect}
|
|
4591
|
+
CASE
|
|
4592
|
+
WHEN att.atttypid IN (1042, 1043) THEN (att.atttypmod - 4)::int4
|
|
4593
|
+
WHEN att.atttypid IN (1560, 1562) THEN (att.atttypmod)::int4
|
|
4594
|
+
ELSE NULL
|
|
4595
|
+
END AS max_length,
|
|
4596
|
+
des.description AS comment,
|
|
4597
|
+
CASE att.atttypid
|
|
4598
|
+
WHEN 21 THEN 16
|
|
4599
|
+
WHEN 23 THEN 32
|
|
4600
|
+
WHEN 20 THEN 64
|
|
4601
|
+
WHEN 1700 THEN
|
|
4602
|
+
CASE WHEN atttypmod = -1 THEN NULL
|
|
4603
|
+
ELSE (((atttypmod - 4) >> 16) & 65535)::int4
|
|
4604
|
+
END
|
|
4605
|
+
WHEN 700 THEN 24
|
|
4606
|
+
WHEN 701 THEN 53
|
|
4607
|
+
ELSE NULL
|
|
4608
|
+
END AS numeric_precision,
|
|
4609
|
+
CASE
|
|
4610
|
+
WHEN atttypid IN (21, 23, 20) THEN 0
|
|
4611
|
+
WHEN atttypid = 1700 THEN
|
|
4612
|
+
CASE
|
|
4613
|
+
WHEN atttypmod = -1 THEN NULL
|
|
4614
|
+
ELSE ((atttypmod - 4) & 65535)::int4
|
|
4615
|
+
END
|
|
4616
|
+
ELSE null
|
|
4617
|
+
END AS numeric_scale
|
|
4618
|
+
FROM
|
|
4619
|
+
pg_attribute att
|
|
4620
|
+
LEFT JOIN pg_class rel ON att.attrelid = rel.oid
|
|
4621
|
+
LEFT JOIN pg_attrdef ad ON (att.attrelid, att.attnum) = (ad.adrelid, ad.adnum)
|
|
4622
|
+
LEFT JOIN pg_description des ON (att.attrelid, att.attnum) = (des.objoid, des.objsubid)
|
|
4623
|
+
WHERE
|
|
4624
|
+
rel.relnamespace IN (${schemaIn})
|
|
4625
|
+
${table ? "AND rel.relname = ?" : ""}
|
|
4626
|
+
${column ? "AND att.attname = ?" : ""}
|
|
4627
|
+
AND rel.relkind = 'r'
|
|
4628
|
+
AND att.attnum > 0
|
|
4629
|
+
AND NOT att.attisdropped
|
|
4630
|
+
ORDER BY rel.relname, att.attnum;
|
|
4631
|
+
`, bindings), knex$1.raw(`
|
|
4632
|
+
SELECT
|
|
4633
|
+
con.contype AS type,
|
|
4634
|
+
rel.relname AS table,
|
|
4635
|
+
att.attname AS column,
|
|
4636
|
+
frel.relnamespace::regnamespace::text AS foreign_key_schema,
|
|
4637
|
+
frel.relname AS foreign_key_table,
|
|
4638
|
+
fatt.attname AS foreign_key_column,
|
|
4639
|
+
CASE
|
|
4640
|
+
WHEN con.contype = 'p' THEN pg_get_serial_sequence(att.attrelid::regclass::text, att.attname) != ''
|
|
4641
|
+
ELSE NULL
|
|
4642
|
+
END AS has_auto_increment
|
|
4643
|
+
FROM
|
|
4644
|
+
pg_constraint con
|
|
4645
|
+
LEFT JOIN pg_class rel ON con.conrelid = rel.oid
|
|
4646
|
+
LEFT JOIN pg_class frel ON con.confrelid = frel.oid
|
|
4647
|
+
LEFT JOIN pg_attribute att ON att.attrelid = con.conrelid AND att.attnum = con.conkey[1]
|
|
4648
|
+
LEFT JOIN pg_attribute fatt ON fatt.attrelid = con.confrelid AND fatt.attnum = con.confkey[1]
|
|
4649
|
+
WHERE con.connamespace IN (${schemaIn})
|
|
4650
|
+
AND array_length(con.conkey, 1) <= 1
|
|
4651
|
+
AND (con.confkey IS NULL OR array_length(con.confkey, 1) = 1)
|
|
4652
|
+
${table ? "AND rel.relname = ?" : ""}
|
|
4653
|
+
${column ? "AND att.attname = ?" : ""}
|
|
4654
|
+
`, bindings)]);
|
|
4655
|
+
const parsedColumms = columns.rows.map((col) => {
|
|
4656
|
+
const constraintsForColumn = constraints.rows.filter((constraint) => constraint.table === col.table && constraint.column === col.name);
|
|
4657
|
+
const foreignKeyConstraint = constraintsForColumn.find((constraint) => constraint.type === "f");
|
|
4658
|
+
return {
|
|
4659
|
+
...col,
|
|
4660
|
+
is_unique: constraintsForColumn.some((constraint) => ["u", "p"].includes(constraint.type)),
|
|
4661
|
+
is_primary_key: constraintsForColumn.some((constraint) => constraint.type === "p"),
|
|
4662
|
+
has_auto_increment: constraintsForColumn.some((constraint) => constraint.has_auto_increment),
|
|
4663
|
+
default_value: parseDefaultValue$1(col.default_value),
|
|
4664
|
+
foreign_key_schema: (foreignKeyConstraint === null || foreignKeyConstraint === void 0 ? void 0 : foreignKeyConstraint.foreign_key_schema) ?? null,
|
|
4665
|
+
foreign_key_table: (foreignKeyConstraint === null || foreignKeyConstraint === void 0 ? void 0 : foreignKeyConstraint.foreign_key_table) ?? null,
|
|
4666
|
+
foreign_key_column: (foreignKeyConstraint === null || foreignKeyConstraint === void 0 ? void 0 : foreignKeyConstraint.foreign_key_column) ?? null
|
|
4667
|
+
};
|
|
4668
|
+
});
|
|
4669
|
+
if (table && column) return parsedColumms[0];
|
|
4670
|
+
return parsedColumms;
|
|
4671
|
+
}
|
|
4672
|
+
/**
|
|
4673
|
+
* Check if the given table contains the given column
|
|
4674
|
+
*/
|
|
4675
|
+
async hasColumn(table, column) {
|
|
4676
|
+
const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
|
|
4677
|
+
return (await this.knex.raw(`
|
|
4678
|
+
SELECT
|
|
4679
|
+
att.attname AS column,
|
|
4680
|
+
rel.relname AS table
|
|
4681
|
+
FROM
|
|
4682
|
+
pg_attribute att
|
|
4683
|
+
LEFT JOIN pg_class rel ON att.attrelid = rel.oid
|
|
4684
|
+
WHERE
|
|
4685
|
+
rel.relnamespace IN (${schemaIn})
|
|
4686
|
+
AND rel.relname = ?
|
|
4687
|
+
AND att.attname = ?
|
|
4688
|
+
AND rel.relkind = 'r'
|
|
4689
|
+
AND att.attnum > 0
|
|
4690
|
+
AND NOT att.attisdropped;
|
|
4691
|
+
`, [table, column])).rows;
|
|
4692
|
+
}
|
|
4693
|
+
/**
|
|
4694
|
+
* Get the primary key column for the given table
|
|
4695
|
+
*/
|
|
4696
|
+
async primary(table) {
|
|
4697
|
+
const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
|
|
4698
|
+
const result = await this.knex.raw(`
|
|
4699
|
+
SELECT
|
|
4700
|
+
att.attname AS column
|
|
4701
|
+
FROM
|
|
4702
|
+
pg_constraint con
|
|
4703
|
+
LEFT JOIN pg_class rel ON con.conrelid = rel.oid
|
|
4704
|
+
LEFT JOIN pg_attribute att ON att.attrelid = con.conrelid AND att.attnum = ANY(con.conkey)
|
|
4705
|
+
WHERE con.connamespace IN (${schemaIn})
|
|
4706
|
+
AND con.contype = 'p'
|
|
4707
|
+
AND rel.relname = ?
|
|
4708
|
+
`, [table]);
|
|
4709
|
+
return result.rows.length !== 0 ? result.rows.length === 1 ? result.rows[0].column : result.rows.map((r) => r.column) : null;
|
|
4710
|
+
}
|
|
4711
|
+
async foreignKeys(table) {
|
|
4712
|
+
const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
|
|
4713
|
+
const bindings = [];
|
|
4714
|
+
if (table) bindings.push(table);
|
|
4715
|
+
return (await this.knex.raw(`
|
|
4716
|
+
SELECT
|
|
4717
|
+
con.conname AS constraint_name,
|
|
4718
|
+
rel.relname AS table,
|
|
4719
|
+
att.attname AS column,
|
|
4720
|
+
frel.relnamespace::regnamespace::text AS foreign_key_schema,
|
|
4721
|
+
frel.relname AS foreign_key_table,
|
|
4722
|
+
fatt.attname AS foreign_key_column,
|
|
4723
|
+
CASE con.confupdtype
|
|
4724
|
+
WHEN 'r' THEN
|
|
4725
|
+
'RESTRICT'
|
|
4726
|
+
WHEN 'c' THEN
|
|
4727
|
+
'CASCADE'
|
|
4728
|
+
WHEN 'n' THEN
|
|
4729
|
+
'SET NULL'
|
|
4730
|
+
WHEN 'd' THEN
|
|
4731
|
+
'SET DEFAULT'
|
|
4732
|
+
WHEN 'a' THEN
|
|
4733
|
+
'NO ACTION'
|
|
4734
|
+
ELSE
|
|
4735
|
+
NULL
|
|
4736
|
+
END AS on_update,
|
|
4737
|
+
CASE con.confdeltype
|
|
4738
|
+
WHEN 'r' THEN
|
|
4739
|
+
'RESTRICT'
|
|
4740
|
+
WHEN 'c' THEN
|
|
4741
|
+
'CASCADE'
|
|
4742
|
+
WHEN 'n' THEN
|
|
4743
|
+
'SET NULL'
|
|
4744
|
+
WHEN 'd' THEN
|
|
4745
|
+
'SET DEFAULT'
|
|
4746
|
+
WHEN 'a' THEN
|
|
4747
|
+
'NO ACTION'
|
|
4748
|
+
ELSE
|
|
4749
|
+
NULL
|
|
4750
|
+
END AS on_delete
|
|
4751
|
+
FROM
|
|
4752
|
+
pg_constraint con
|
|
4753
|
+
LEFT JOIN pg_class rel ON con.conrelid = rel.oid
|
|
4754
|
+
LEFT JOIN pg_class frel ON con.confrelid = frel.oid
|
|
4755
|
+
LEFT JOIN pg_attribute att ON att.attrelid = con.conrelid AND att.attnum = con.conkey[1]
|
|
4756
|
+
LEFT JOIN pg_attribute fatt ON fatt.attrelid = con.confrelid AND fatt.attnum = con.confkey[1]
|
|
4757
|
+
WHERE con.connamespace IN (${schemaIn})
|
|
4758
|
+
AND array_length(con.conkey, 1) <= 1
|
|
4759
|
+
AND (con.confkey IS NULL OR array_length(con.confkey, 1) = 1)
|
|
4760
|
+
AND con.contype = 'f'
|
|
4761
|
+
${table ? "AND rel.relname = ?" : ""}
|
|
4762
|
+
`, bindings)).rows;
|
|
4763
|
+
}
|
|
4764
|
+
async uniqueConstraints(table) {
|
|
4765
|
+
const { knex: knex$1 } = this;
|
|
4766
|
+
const schemaIn = this.explodedSchema.map((schemaName) => `${this.knex.raw("?", [schemaName])}::regnamespace`);
|
|
4767
|
+
const bindings = [];
|
|
4768
|
+
if (table) bindings.push(table);
|
|
4769
|
+
return (await knex$1.raw(`
|
|
4770
|
+
SELECT
|
|
4771
|
+
con.conrelid::regclass AS table_name,
|
|
4772
|
+
con.conname AS constraint_name,
|
|
4773
|
+
array_agg(a.attname ORDER BY k.n) AS columns
|
|
4774
|
+
FROM
|
|
4775
|
+
pg_constraint AS con
|
|
4776
|
+
CROSS JOIN LATERAL unnest(con.conkey) WITH ORDINALITY AS k(con,n)
|
|
4777
|
+
LEFT JOIN pg_class rel ON con.conrelid = rel.oid
|
|
4778
|
+
JOIN pg_attribute AS a ON a.attnum = k.con AND a.attrelid = con.conrelid
|
|
4779
|
+
WHERE con.contype = 'u'
|
|
4780
|
+
AND con.connamespace IN (${schemaIn})
|
|
4781
|
+
${table ? "AND rel.relname = ?" : ""}
|
|
4782
|
+
GROUP BY con.oid, con.conrelid, con.conname;
|
|
4783
|
+
`, bindings)).rows.map((v) => {
|
|
4784
|
+
const columns = Array.isArray(v.columns) ? v.columns : v.columns.substring(1, v.columns.length - 1).split(",");
|
|
4785
|
+
return {
|
|
4786
|
+
table: v.table_name,
|
|
4787
|
+
constraint_name: v.constraint_name,
|
|
4788
|
+
columns
|
|
4789
|
+
};
|
|
4790
|
+
});
|
|
4791
|
+
}
|
|
4792
|
+
};
|
|
4793
|
+
|
|
4794
|
+
//#endregion
|
|
4795
|
+
//#region src/inspector/utils/extract-max-length.ts
|
|
4796
|
+
/**
|
|
4797
|
+
* Extracts the length value out of a given datatype
|
|
4798
|
+
* For example: `varchar(32)` => 32
|
|
4799
|
+
*/
|
|
4800
|
+
function extractMaxLength(type) {
|
|
4801
|
+
const matches = /\(([^)]+)\)/.exec(type);
|
|
4802
|
+
if (matches && matches.length > 0 && matches[1]) return Number(matches[1]);
|
|
4803
|
+
return null;
|
|
4804
|
+
}
|
|
4805
|
+
|
|
4806
|
+
//#endregion
|
|
4807
|
+
//#region src/inspector/utils/extract-type.ts
|
|
4808
|
+
/**
|
|
4809
|
+
* Extracts the type out of a given datatype
|
|
4810
|
+
* For example: `varchar(32)` => varchar
|
|
4811
|
+
*/
|
|
4812
|
+
function extractType(type) {
|
|
4813
|
+
return type.replace(/[^a-zA-Z]/g, "").toLowerCase();
|
|
4814
|
+
}
|
|
4815
|
+
|
|
4816
|
+
//#endregion
|
|
4817
|
+
//#region src/inspector/dialects/sqlite.ts
|
|
4818
|
+
function parseDefaultValue(value) {
|
|
4819
|
+
if (value === null || value.trim().toLowerCase() === "null") return null;
|
|
4820
|
+
return stripQuotes(value);
|
|
4821
|
+
}
|
|
4822
|
+
var SQLite = class {
|
|
4823
|
+
knex;
|
|
4824
|
+
constructor(knex$1) {
|
|
4825
|
+
this.knex = knex$1;
|
|
4826
|
+
}
|
|
4827
|
+
/**
|
|
4828
|
+
* List all existing tables in the current schema/database
|
|
4829
|
+
*/
|
|
4830
|
+
async tables() {
|
|
4831
|
+
return (await this.knex.select("name").from("sqlite_master").whereRaw("type = 'table' AND name NOT LIKE 'sqlite_%'")).map(({ name }) => name);
|
|
4832
|
+
}
|
|
4833
|
+
async tableInfo(table) {
|
|
4834
|
+
const query = this.knex.select("name", "sql").from("sqlite_master").where({ type: "table" }).andWhereRaw("name NOT LIKE 'sqlite_%'");
|
|
4835
|
+
if (table) query.andWhere({ name: table });
|
|
4836
|
+
let records = await query;
|
|
4837
|
+
records = records.map((table$1) => ({
|
|
4838
|
+
name: table$1.name,
|
|
4839
|
+
sql: table$1.sql
|
|
4840
|
+
}));
|
|
4841
|
+
if (table) return records[0];
|
|
4842
|
+
return records;
|
|
4843
|
+
}
|
|
4844
|
+
/**
|
|
4845
|
+
* Check if a table exists in the current schema/database
|
|
4846
|
+
*/
|
|
4847
|
+
async hasTable(table) {
|
|
4848
|
+
return (await this.knex.select(1).from("sqlite_master").where({
|
|
4849
|
+
type: "table",
|
|
4850
|
+
name: table
|
|
4851
|
+
})).length > 0;
|
|
4852
|
+
}
|
|
4853
|
+
/**
|
|
4854
|
+
* Get all the available columns in the current schema/database. Can be filtered to a specific table
|
|
4855
|
+
*/
|
|
4856
|
+
async columns(table) {
|
|
4857
|
+
if (table) return (await this.knex.raw("PRAGMA table_xinfo(??)", table)).map((column) => ({
|
|
4858
|
+
table,
|
|
4859
|
+
column: column.name
|
|
4860
|
+
}));
|
|
4861
|
+
const tables = await this.tables();
|
|
4862
|
+
const columnsPerTable = await Promise.all(tables.map(async (table$1) => await this.columns(table$1)));
|
|
4863
|
+
return flatten(columnsPerTable);
|
|
4864
|
+
}
|
|
4865
|
+
async columnInfo(table, column) {
|
|
4866
|
+
const getColumnsForTable = async (table$1) => {
|
|
4867
|
+
const tablesWithAutoIncrementPrimaryKeys = (await this.knex.select("name").from("sqlite_master").whereRaw("sql LIKE '%AUTOINCREMENT%'")).map(({ name }) => name);
|
|
4868
|
+
const columns = await this.knex.raw("PRAGMA table_xinfo(??)", table$1);
|
|
4869
|
+
const foreignKeys = await this.knex.raw("PRAGMA foreign_key_list(??)", table$1);
|
|
4870
|
+
const indexList = await this.knex.raw("PRAGMA index_list(??)", table$1);
|
|
4871
|
+
const indexInfoList = await Promise.all(indexList.map((index) => this.knex.raw("PRAGMA index_info(??)", index.name)));
|
|
4872
|
+
return columns.map((raw) => {
|
|
4873
|
+
const foreignKey = foreignKeys.find((fk) => fk.from === raw.name);
|
|
4874
|
+
const indexIndex = indexInfoList.findIndex((list) => list.find((fk) => fk.name === raw.name));
|
|
4875
|
+
const index = indexList[indexIndex];
|
|
4876
|
+
const indexInfo = indexInfoList[indexIndex];
|
|
4877
|
+
return {
|
|
4878
|
+
name: raw.name,
|
|
4879
|
+
table: table$1,
|
|
4880
|
+
data_type: extractType(raw.type),
|
|
4881
|
+
default_value: parseDefaultValue(raw.dflt_value),
|
|
4882
|
+
max_length: extractMaxLength(raw.type),
|
|
4883
|
+
numeric_precision: null,
|
|
4884
|
+
numeric_scale: null,
|
|
4885
|
+
is_generated: raw.hidden !== 0,
|
|
4886
|
+
generation_expression: null,
|
|
4887
|
+
is_nullable: raw.notnull === 0,
|
|
4888
|
+
is_unique: !!(index === null || index === void 0 ? void 0 : index.unique) && (indexInfo === null || indexInfo === void 0 ? void 0 : indexInfo.length) === 1,
|
|
4889
|
+
is_primary_key: raw.pk === 1,
|
|
4890
|
+
has_auto_increment: raw.pk === 1 && tablesWithAutoIncrementPrimaryKeys.includes(table$1),
|
|
4891
|
+
foreign_key_column: (foreignKey === null || foreignKey === void 0 ? void 0 : foreignKey.to) || null,
|
|
4892
|
+
foreign_key_table: (foreignKey === null || foreignKey === void 0 ? void 0 : foreignKey.table) || null
|
|
4893
|
+
};
|
|
4894
|
+
});
|
|
4895
|
+
};
|
|
4896
|
+
if (!table) {
|
|
4897
|
+
const tables = await this.tables();
|
|
4898
|
+
const columnsPerTable = await Promise.all(tables.map(async (table$1) => await getColumnsForTable(table$1)));
|
|
4899
|
+
return flatten(columnsPerTable);
|
|
4900
|
+
}
|
|
4901
|
+
if (table && !column) return await getColumnsForTable(table);
|
|
4902
|
+
return (await getColumnsForTable(table)).find((columnInfo) => columnInfo.name === column);
|
|
4903
|
+
}
|
|
4904
|
+
/**
|
|
4905
|
+
* Check if a table exists in the current schema/database
|
|
4906
|
+
*/
|
|
4907
|
+
async hasColumn(table, column) {
|
|
4908
|
+
let isColumn = false;
|
|
4909
|
+
if ((await this.knex.raw(`SELECT COUNT(*) AS ct FROM pragma_table_xinfo('${table}') WHERE name='${column}'`))[0]["ct"] !== 0) isColumn = true;
|
|
4910
|
+
return isColumn;
|
|
4911
|
+
}
|
|
4912
|
+
/**
|
|
4913
|
+
* Get the primary key column for the given table
|
|
4914
|
+
*/
|
|
4915
|
+
async primary(table) {
|
|
4916
|
+
const pkColumns = (await this.knex.raw("PRAGMA table_xinfo(??)", table)).filter((col) => col.pk !== 0);
|
|
4917
|
+
return pkColumns.length > 0 ? pkColumns.length === 1 ? pkColumns[0].name : pkColumns.map((col) => col.name) : null;
|
|
4918
|
+
}
|
|
4919
|
+
async foreignKeys(table) {
|
|
4920
|
+
if (table) return (await this.knex.raw("PRAGMA foreign_key_list(??)", table)).map((key) => ({
|
|
4921
|
+
table,
|
|
4922
|
+
column: key.from,
|
|
4923
|
+
foreign_key_table: key.table,
|
|
4924
|
+
foreign_key_column: key.to,
|
|
4925
|
+
on_update: key.on_update,
|
|
4926
|
+
on_delete: key.on_delete,
|
|
4927
|
+
constraint_name: null
|
|
4928
|
+
}));
|
|
4929
|
+
const tables = await this.tables();
|
|
4930
|
+
const keysPerTable = await Promise.all(tables.map(async (table$1) => await this.foreignKeys(table$1)));
|
|
4931
|
+
return flatten(keysPerTable);
|
|
4932
|
+
}
|
|
4933
|
+
async uniqueConstraints(table) {
|
|
4934
|
+
if (table) {
|
|
4935
|
+
const indexList = await this.knex.raw("PRAGMA index_list(??)", table);
|
|
4936
|
+
const indexInfoList = await Promise.all(indexList.map((index) => this.knex.raw("PRAGMA index_info(??)", index.name)));
|
|
4937
|
+
return indexList.filter((i) => i.unique).map((index, i) => {
|
|
4938
|
+
const info = indexInfoList[i];
|
|
4939
|
+
return {
|
|
4940
|
+
table,
|
|
4941
|
+
constraint_name: index.name,
|
|
4942
|
+
columns: info.map((c) => c.name)
|
|
4943
|
+
};
|
|
4944
|
+
});
|
|
4945
|
+
}
|
|
4946
|
+
const tables = await this.tables();
|
|
4947
|
+
const constraintsPerTable = await Promise.all(tables.map(async (table$1) => await this.uniqueConstraints(table$1)));
|
|
4948
|
+
return flatten(constraintsPerTable);
|
|
4949
|
+
}
|
|
4950
|
+
};
|
|
4951
|
+
|
|
4952
|
+
//#endregion
|
|
4953
|
+
//#region src/inspector/index.ts
|
|
4954
|
+
var SchemaInspector = class {
|
|
4955
|
+
static inspect(knex$1) {
|
|
4956
|
+
let constructor;
|
|
4957
|
+
switch (knex$1.client.constructor.name) {
|
|
4958
|
+
case "Client_MySQL":
|
|
4959
|
+
case "Client_MySQL2":
|
|
4960
|
+
constructor = MySQL;
|
|
4961
|
+
break;
|
|
4962
|
+
case "Client_PG":
|
|
4963
|
+
constructor = Postgres;
|
|
4964
|
+
break;
|
|
4965
|
+
case "Client_CockroachDB":
|
|
4966
|
+
constructor = CockroachDB;
|
|
4967
|
+
break;
|
|
4968
|
+
case "Client_SQLite3":
|
|
4969
|
+
case "Client_BetterSQLite3":
|
|
4970
|
+
constructor = SQLite;
|
|
4971
|
+
break;
|
|
4972
|
+
case "Client_Oracledb":
|
|
4973
|
+
case "Client_Oracle":
|
|
4974
|
+
constructor = oracleDB;
|
|
4975
|
+
break;
|
|
4976
|
+
case "Client_MSSQL":
|
|
4977
|
+
constructor = MSSQL;
|
|
4978
|
+
break;
|
|
4979
|
+
default: throw Error("Unsupported driver used: " + knex$1.client.constructor.name);
|
|
4980
|
+
}
|
|
4981
|
+
return new constructor(knex$1);
|
|
4982
|
+
}
|
|
4983
|
+
};
|
|
4984
|
+
|
|
3567
4985
|
//#endregion
|
|
3568
4986
|
//#region src/migrations/migrator.ts
|
|
3569
4987
|
async function glob(folderPath) {
|
|
@@ -3605,14 +5023,14 @@ var Migrator = class {
|
|
|
3605
5023
|
return Object.values(files).filter((file) => !ran.includes(this.getMigrationName(file)));
|
|
3606
5024
|
}
|
|
3607
5025
|
async runPending(migrations, options = {}) {
|
|
3608
|
-
if (migrations.length === 0) {
|
|
3609
|
-
|
|
5026
|
+
if (migrations.length === 0 && !options.quiet) {
|
|
5027
|
+
__h3ravel_shared.Logger.info("INFO: Nothing to migrate.");
|
|
3610
5028
|
return;
|
|
3611
5029
|
}
|
|
3612
5030
|
let batch = await this.repository.getNextBatchNumber();
|
|
3613
5031
|
const pretend = options.pretend || false;
|
|
3614
5032
|
const step = options.step || false;
|
|
3615
|
-
|
|
5033
|
+
__h3ravel_shared.Logger.info("INFO: Running migrations...");
|
|
3616
5034
|
for (const file of migrations) {
|
|
3617
5035
|
await this.runUp(file, batch, pretend);
|
|
3618
5036
|
if (step) batch++;
|
|
@@ -3621,19 +5039,19 @@ var Migrator = class {
|
|
|
3621
5039
|
async runUp(file, batch, _pretend) {
|
|
3622
5040
|
const migration = await this.resolvePath(file);
|
|
3623
5041
|
const name = this.getMigrationName(file);
|
|
3624
|
-
await
|
|
5042
|
+
await __h3ravel_shared.TaskManager.taskRunner(name, () => this.runMigration(migration, "up"));
|
|
3625
5043
|
await this.repository.log(name, batch);
|
|
3626
5044
|
}
|
|
3627
5045
|
async runDown(file, migration, _pretend) {
|
|
3628
5046
|
const instance = await this.resolvePath(file);
|
|
3629
5047
|
const name = this.getMigrationName(file);
|
|
3630
|
-
await
|
|
5048
|
+
await __h3ravel_shared.TaskManager.taskRunner(name, () => this.runMigration(instance, "down"));
|
|
3631
5049
|
await this.repository.delete(migration);
|
|
3632
5050
|
}
|
|
3633
5051
|
async rollback(paths = [], options = {}) {
|
|
3634
5052
|
const migrations = await this.getMigrationsForRollback(options);
|
|
3635
5053
|
if (migrations.length === 0) {
|
|
3636
|
-
|
|
5054
|
+
__h3ravel_shared.Logger.info("INFO: Nothing to rollback");
|
|
3637
5055
|
return [];
|
|
3638
5056
|
}
|
|
3639
5057
|
return await this.rollbackMigrations(migrations, paths, options);
|
|
@@ -3646,7 +5064,7 @@ var Migrator = class {
|
|
|
3646
5064
|
async rollbackMigrations(migrations, paths, options) {
|
|
3647
5065
|
const rolledBack = [];
|
|
3648
5066
|
const files = await this.getMigrationFiles(paths);
|
|
3649
|
-
|
|
5067
|
+
__h3ravel_shared.Logger.info("INFO: Rolling back migrations...");
|
|
3650
5068
|
for (const migration of migrations) {
|
|
3651
5069
|
const file = files[migration.migration];
|
|
3652
5070
|
if (!file) {
|
|
@@ -3658,11 +5076,35 @@ var Migrator = class {
|
|
|
3658
5076
|
}
|
|
3659
5077
|
return rolledBack;
|
|
3660
5078
|
}
|
|
3661
|
-
reset(
|
|
3662
|
-
this.repository.getRan().then((r) => r.reverse());
|
|
3663
|
-
|
|
5079
|
+
async reset(paths = [], options, pretend = false) {
|
|
5080
|
+
const migrations = await this.repository.getRan().then((r) => r.map((e) => ({ migration: e })).reverse());
|
|
5081
|
+
if (migrations.length === 0) {
|
|
5082
|
+
if (!options.quiet) __h3ravel_shared.Logger.info("INFO: Nothing to reset.");
|
|
5083
|
+
return [];
|
|
5084
|
+
}
|
|
5085
|
+
return this.resetMigrations(migrations, paths, pretend);
|
|
3664
5086
|
}
|
|
3665
|
-
|
|
5087
|
+
/**
|
|
5088
|
+
* Drop all tables and re-run all migrations
|
|
5089
|
+
*
|
|
5090
|
+
* @param paths
|
|
5091
|
+
* @param options
|
|
5092
|
+
*/
|
|
5093
|
+
async fresh(paths, options) {
|
|
5094
|
+
/** Initialise connections */
|
|
5095
|
+
const connection = this.repository.getConnection().connector;
|
|
5096
|
+
const inspector = SchemaInspector.inspect(connection);
|
|
5097
|
+
await connection.raw("SET foreign_key_checks = 0");
|
|
5098
|
+
/** Drop all existing tables */
|
|
5099
|
+
for (const table of await inspector.tables()) await __h3ravel_shared.TaskManager.taskRunner(`Dropping ${__h3ravel_shared.Logger.parse([[table, "grey"]], "", false)} table`, () => connection.schema.dropTableIfExists(table));
|
|
5100
|
+
await connection.raw("SET foreign_key_checks = 1");
|
|
5101
|
+
/** Create the migration repository */
|
|
5102
|
+
await this.repository.createRepository();
|
|
5103
|
+
console.log();
|
|
5104
|
+
/** Run fresh migrations */
|
|
5105
|
+
await this.run(paths, options);
|
|
5106
|
+
}
|
|
5107
|
+
async resetMigrations(migrations, paths, pretend = false) {
|
|
3666
5108
|
return this.rollbackMigrations(migrations, paths, { pretend });
|
|
3667
5109
|
}
|
|
3668
5110
|
async runMigration(migration, method) {
|
|
@@ -3713,7 +5155,7 @@ var Migrator = class {
|
|
|
3713
5155
|
return this.connection;
|
|
3714
5156
|
}
|
|
3715
5157
|
resolveConnection(connection) {
|
|
3716
|
-
return this.resolver.
|
|
5158
|
+
return this.resolver.fire(connection || this.connection);
|
|
3717
5159
|
}
|
|
3718
5160
|
getRepository() {
|
|
3719
5161
|
return this.repository;
|
|
@@ -3735,17 +5177,6 @@ var Migrator = class {
|
|
|
3735
5177
|
write(...args) {
|
|
3736
5178
|
if (this.output) console.log(...args);
|
|
3737
5179
|
}
|
|
3738
|
-
async writeTask(description, task) {
|
|
3739
|
-
const startTime = process.hrtime();
|
|
3740
|
-
let result = false;
|
|
3741
|
-
try {
|
|
3742
|
-
result = await (task || (() => true))();
|
|
3743
|
-
} finally {
|
|
3744
|
-
const endTime = process.hrtime(startTime);
|
|
3745
|
-
const duration = (endTime[0] * 1e9 + endTime[1]) / 1e6;
|
|
3746
|
-
__h3ravel_shared.Logger.twoColumnLog(__h3ravel_shared.Logger.parse([[description, "green"]], "", false), [__h3ravel_shared.Logger.parse([[`${Math.floor(duration)}ms`, "gray"]], "", false), __h3ravel_shared.Logger.parse([[result !== false ? "✔" : "✘", result !== false ? "green" : "red"]], "", false)].join(" "));
|
|
3747
|
-
}
|
|
3748
|
-
}
|
|
3749
5180
|
};
|
|
3750
5181
|
var migrator_default = Migrator;
|
|
3751
5182
|
|
|
@@ -3846,6 +5277,49 @@ var Migrate = class {
|
|
|
3846
5277
|
if (destroyAll) await arquebus$1.destroyAll();
|
|
3847
5278
|
}
|
|
3848
5279
|
/**
|
|
5280
|
+
* Rollback all database migrations
|
|
5281
|
+
*
|
|
5282
|
+
* @param config
|
|
5283
|
+
* @param options
|
|
5284
|
+
* @param destroyAll
|
|
5285
|
+
*/
|
|
5286
|
+
async reset(config, options = {}, destroyAll = false) {
|
|
5287
|
+
const { arquebus: arquebus$1, migrator } = await this.setupConnection(config);
|
|
5288
|
+
const paths = await Utils.getMigrationPaths(this.basePath ?? process.cwd(), migrator, config.migrations.path, options.path);
|
|
5289
|
+
await migrator.setOutput(true).reset(paths, {
|
|
5290
|
+
step: options.step || 0,
|
|
5291
|
+
pretend: options.pretend,
|
|
5292
|
+
batch: options.batch || 0,
|
|
5293
|
+
quiet: options.quiet || false
|
|
5294
|
+
});
|
|
5295
|
+
if (destroyAll) await arquebus$1.destroyAll();
|
|
5296
|
+
}
|
|
5297
|
+
/**
|
|
5298
|
+
* Reset and re-run all migrations
|
|
5299
|
+
*
|
|
5300
|
+
* @param config
|
|
5301
|
+
* @param options
|
|
5302
|
+
* @param destroyAll
|
|
5303
|
+
*/
|
|
5304
|
+
async refresh(config, options = {}, destroyAll = false) {
|
|
5305
|
+
await this.reset(config, Object.assign({}, options, { quiet: true }), false);
|
|
5306
|
+
console.log("");
|
|
5307
|
+
await this.run(config, options, destroyAll);
|
|
5308
|
+
}
|
|
5309
|
+
/**
|
|
5310
|
+
* Drop all tables and re-run all migrations
|
|
5311
|
+
*
|
|
5312
|
+
* @param config
|
|
5313
|
+
* @param options
|
|
5314
|
+
* @param destroyAll
|
|
5315
|
+
*/
|
|
5316
|
+
async fresh(config, options = {}, destroyAll = false) {
|
|
5317
|
+
const { arquebus: arquebus$1, migrator } = await this.setupConnection(config);
|
|
5318
|
+
const paths = await Utils.getMigrationPaths(this.basePath ?? process.cwd(), migrator, config.migrations.path, options.path);
|
|
5319
|
+
await migrator.setOutput(true).fresh(paths, { pretend: options.pretend });
|
|
5320
|
+
if (destroyAll) await arquebus$1.destroyAll();
|
|
5321
|
+
}
|
|
5322
|
+
/**
|
|
3849
5323
|
* Prepares the database for migration
|
|
3850
5324
|
*
|
|
3851
5325
|
* @param migrator
|
|
@@ -4122,6 +5596,7 @@ exports.SoftDeletes = soft_deletes_default;
|
|
|
4122
5596
|
exports.arquebus = arquebus_default;
|
|
4123
5597
|
exports.compose = compose;
|
|
4124
5598
|
exports.defineConfig = defineConfig;
|
|
5599
|
+
exports.flatten = flatten;
|
|
4125
5600
|
exports.flattenDeep = flattenDeep;
|
|
4126
5601
|
exports.getAttrMethod = getAttrMethod;
|
|
4127
5602
|
exports.getAttrName = getAttrName;
|