rake-db 2.4.39 → 2.4.41
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/dist/index.d.ts +27 -1
- package/dist/index.js +329 -152
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +331 -154
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -115,12 +115,16 @@ declare class MigrationBase {
|
|
|
115
115
|
dropEnum(name: string, values: [string, ...string[]], options?: Omit<RakeDbAst.Enum, 'type' | 'action' | 'name' | 'values' | 'schema'>): Promise<void>;
|
|
116
116
|
createDomain(name: string, fn: (t: ColumnTypes) => ColumnType, options?: Omit<RakeDbAst.Domain, 'type' | 'action' | 'schema' | 'name' | 'baseType'>): Promise<void>;
|
|
117
117
|
dropDomain(name: string, fn: (t: ColumnTypes) => ColumnType, options?: Omit<RakeDbAst.Domain, 'type' | 'action' | 'schema' | 'name' | 'baseType'>): Promise<void>;
|
|
118
|
+
createView(name: string, options: RakeDbAst.ViewOptions, sql: string | RawExpression): Promise<void>;
|
|
119
|
+
createView(name: string, sql: string | RawExpression): Promise<void>;
|
|
120
|
+
dropView(name: string, options: RakeDbAst.ViewOptions, sql: string | RawExpression): Promise<void>;
|
|
121
|
+
dropView(name: string, sql: string | RawExpression): Promise<void>;
|
|
118
122
|
tableExists(tableName: string): Promise<boolean>;
|
|
119
123
|
columnExists(tableName: string, columnName: string): Promise<boolean>;
|
|
120
124
|
constraintExists(constraintName: string): Promise<boolean>;
|
|
121
125
|
}
|
|
122
126
|
|
|
123
|
-
declare type RakeDbAst = RakeDbAst.Table | RakeDbAst.ChangeTable | RakeDbAst.RenameTable | RakeDbAst.Schema | RakeDbAst.Extension | RakeDbAst.Enum | RakeDbAst.Domain | RakeDbAst.Constraint;
|
|
127
|
+
declare type RakeDbAst = RakeDbAst.Table | RakeDbAst.ChangeTable | RakeDbAst.RenameTable | RakeDbAst.Schema | RakeDbAst.Extension | RakeDbAst.Enum | RakeDbAst.Domain | RakeDbAst.Constraint | RakeDbAst.View;
|
|
124
128
|
declare namespace RakeDbAst {
|
|
125
129
|
type Table = {
|
|
126
130
|
type: 'table';
|
|
@@ -230,6 +234,28 @@ declare namespace RakeDbAst {
|
|
|
230
234
|
tableSchema?: string;
|
|
231
235
|
tableName: string;
|
|
232
236
|
} & TableData.Constraint;
|
|
237
|
+
type View = {
|
|
238
|
+
type: 'view';
|
|
239
|
+
action: 'create' | 'drop';
|
|
240
|
+
schema?: string;
|
|
241
|
+
name: string;
|
|
242
|
+
shape: ColumnsShape;
|
|
243
|
+
sql: RawExpression;
|
|
244
|
+
options: ViewOptions;
|
|
245
|
+
};
|
|
246
|
+
type ViewOptions = {
|
|
247
|
+
createOrReplace?: boolean;
|
|
248
|
+
dropIfExists?: boolean;
|
|
249
|
+
dropMode?: DropMode;
|
|
250
|
+
temporary?: boolean;
|
|
251
|
+
recursive?: boolean;
|
|
252
|
+
columns?: string[];
|
|
253
|
+
with?: {
|
|
254
|
+
checkOption?: 'LOCAL' | 'CASCADED';
|
|
255
|
+
securityBarrier?: boolean;
|
|
256
|
+
securityInvoker?: boolean;
|
|
257
|
+
};
|
|
258
|
+
};
|
|
233
259
|
}
|
|
234
260
|
|
|
235
261
|
declare type Db = DbResult<DefaultColumnTypes>;
|
package/dist/index.js
CHANGED
|
@@ -582,7 +582,7 @@ const createTable$1 = async (migration, up, tableName, options, fn) => {
|
|
|
582
582
|
types[orchidCore.snakeCaseKey] = snakeCase;
|
|
583
583
|
const shape = pqb.getColumnTypes(types, fn);
|
|
584
584
|
const tableData = pqb.getTableData();
|
|
585
|
-
const ast = makeAst$
|
|
585
|
+
const ast = makeAst$2(
|
|
586
586
|
up,
|
|
587
587
|
tableName,
|
|
588
588
|
shape,
|
|
@@ -608,7 +608,7 @@ const createTable$1 = async (migration, up, tableName, options, fn) => {
|
|
|
608
608
|
}
|
|
609
609
|
};
|
|
610
610
|
};
|
|
611
|
-
const makeAst$
|
|
611
|
+
const makeAst$2 = (up, tableName, shape, tableData, options, noPrimaryKey) => {
|
|
612
612
|
const shapePKeys = [];
|
|
613
613
|
for (const key in shape) {
|
|
614
614
|
const column = shape[key];
|
|
@@ -907,7 +907,7 @@ const changeTable = async (migration, up, tableName, options, fn) => {
|
|
|
907
907
|
const snakeCase = "snakeCase" in options ? options.snakeCase : migration.options.snakeCase;
|
|
908
908
|
tableChanger[orchidCore.snakeCaseKey] = snakeCase;
|
|
909
909
|
const changeData = (fn == null ? void 0 : fn(tableChanger)) || {};
|
|
910
|
-
const ast = makeAst(up, tableName, changeData, changeTableData, options);
|
|
910
|
+
const ast = makeAst$1(up, tableName, changeData, changeTableData, options);
|
|
911
911
|
const queries = astToQueries(ast, snakeCase);
|
|
912
912
|
for (const query of queries) {
|
|
913
913
|
const result = await migration.adapter.arrays(query);
|
|
@@ -915,7 +915,7 @@ const changeTable = async (migration, up, tableName, options, fn) => {
|
|
|
915
915
|
}
|
|
916
916
|
migration.migratedAsts.push(ast);
|
|
917
917
|
};
|
|
918
|
-
const makeAst = (up, name, changeData, changeTableData2, options) => {
|
|
918
|
+
const makeAst$1 = (up, name, changeData, changeTableData2, options) => {
|
|
919
919
|
const { comment } = options;
|
|
920
920
|
const shape = {};
|
|
921
921
|
for (const key in changeData) {
|
|
@@ -1211,6 +1211,68 @@ const mapConstraintsToSnakeCase = (foreignKeys, snakeCase) => {
|
|
|
1211
1211
|
}))) || [];
|
|
1212
1212
|
};
|
|
1213
1213
|
|
|
1214
|
+
const createView$1 = async (migration, up, name, options, sql) => {
|
|
1215
|
+
const ast = makeAst(up, name, options, sql);
|
|
1216
|
+
const query = astToQuery(ast);
|
|
1217
|
+
await migration.adapter.query(query);
|
|
1218
|
+
migration.migratedAsts.push(ast);
|
|
1219
|
+
};
|
|
1220
|
+
const makeAst = (up, name, options, sql) => {
|
|
1221
|
+
if (typeof sql === "string") {
|
|
1222
|
+
sql = orchidCore.raw(sql);
|
|
1223
|
+
}
|
|
1224
|
+
return {
|
|
1225
|
+
type: "view",
|
|
1226
|
+
action: up ? "create" : "drop",
|
|
1227
|
+
name,
|
|
1228
|
+
shape: {},
|
|
1229
|
+
sql,
|
|
1230
|
+
options
|
|
1231
|
+
};
|
|
1232
|
+
};
|
|
1233
|
+
const astToQuery = (ast) => {
|
|
1234
|
+
const values = [];
|
|
1235
|
+
const sql = [];
|
|
1236
|
+
const { options } = ast;
|
|
1237
|
+
if (ast.action === "create") {
|
|
1238
|
+
sql.push("CREATE");
|
|
1239
|
+
if (options == null ? void 0 : options.createOrReplace)
|
|
1240
|
+
sql.push("OR REPLACE");
|
|
1241
|
+
if (options == null ? void 0 : options.temporary)
|
|
1242
|
+
sql.push("TEMPORARY");
|
|
1243
|
+
if (options == null ? void 0 : options.recursive)
|
|
1244
|
+
sql.push("RECURSIVE");
|
|
1245
|
+
sql.push(`VIEW "${ast.name}"`);
|
|
1246
|
+
if (options == null ? void 0 : options.columns) {
|
|
1247
|
+
sql.push(
|
|
1248
|
+
`(${options.columns.map((column) => `"${column}"`).join(", ")})`
|
|
1249
|
+
);
|
|
1250
|
+
}
|
|
1251
|
+
if (options == null ? void 0 : options.with) {
|
|
1252
|
+
const list = [];
|
|
1253
|
+
if (options.with.checkOption)
|
|
1254
|
+
list.push(`check_option = ${orchidCore.singleQuote(options.with.checkOption)}`);
|
|
1255
|
+
if (options.with.securityBarrier)
|
|
1256
|
+
list.push(`security_barrier = true`);
|
|
1257
|
+
if (options.with.securityInvoker)
|
|
1258
|
+
list.push(`security_invoker = true`);
|
|
1259
|
+
sql.push(`WITH ( ${list.join(", ")} )`);
|
|
1260
|
+
}
|
|
1261
|
+
sql.push(`AS (${pqb.getRaw(ast.sql, values)})`);
|
|
1262
|
+
} else {
|
|
1263
|
+
sql.push("DROP VIEW");
|
|
1264
|
+
if (options == null ? void 0 : options.dropIfExists)
|
|
1265
|
+
sql.push(`IF EXISTS`);
|
|
1266
|
+
sql.push(`"${ast.name}"`);
|
|
1267
|
+
if (options == null ? void 0 : options.dropMode)
|
|
1268
|
+
sql.push(options.dropMode);
|
|
1269
|
+
}
|
|
1270
|
+
return {
|
|
1271
|
+
text: sql.join(" "),
|
|
1272
|
+
values
|
|
1273
|
+
};
|
|
1274
|
+
};
|
|
1275
|
+
|
|
1214
1276
|
var __defProp$2 = Object.defineProperty;
|
|
1215
1277
|
var __defProps$1 = Object.defineProperties;
|
|
1216
1278
|
var __getOwnPropDescs$1 = Object.getOwnPropertyDescriptors;
|
|
@@ -1371,6 +1433,26 @@ class MigrationBase {
|
|
|
1371
1433
|
dropDomain(name, fn, options) {
|
|
1372
1434
|
return createDomain$1(this, !this.up, name, fn, options);
|
|
1373
1435
|
}
|
|
1436
|
+
createView(name, ...args) {
|
|
1437
|
+
const [options, sql] = args.length === 2 ? args : [orchidCore.emptyObject, args[0]];
|
|
1438
|
+
return createView$1(
|
|
1439
|
+
this,
|
|
1440
|
+
this.up,
|
|
1441
|
+
name,
|
|
1442
|
+
options,
|
|
1443
|
+
sql
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1446
|
+
dropView(name, ...args) {
|
|
1447
|
+
const [options, sql] = args.length === 2 ? args : [orchidCore.emptyObject, args[0]];
|
|
1448
|
+
return createView$1(
|
|
1449
|
+
this,
|
|
1450
|
+
!this.up,
|
|
1451
|
+
name,
|
|
1452
|
+
options,
|
|
1453
|
+
sql
|
|
1454
|
+
);
|
|
1455
|
+
}
|
|
1374
1456
|
async tableExists(tableName) {
|
|
1375
1457
|
return queryExists(this, {
|
|
1376
1458
|
text: `SELECT 1 FROM "information_schema"."tables" WHERE "table_name" = $1`,
|
|
@@ -1826,79 +1908,14 @@ const makeColumnsContent = (args, method) => {
|
|
|
1826
1908
|
};
|
|
1827
1909
|
|
|
1828
1910
|
const filterSchema = (table) => `${table} !~ '^pg_' AND ${table} != 'information_schema'`;
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
WHERE ${filterSchema("n.nspname")}
|
|
1838
|
-
ORDER BY "name"`
|
|
1839
|
-
);
|
|
1840
|
-
return rows.flat();
|
|
1841
|
-
}
|
|
1842
|
-
async getTables() {
|
|
1843
|
-
const { rows } = await this.db.query(
|
|
1844
|
-
`SELECT
|
|
1845
|
-
nspname AS "schemaName",
|
|
1846
|
-
relname AS "name",
|
|
1847
|
-
obj_description(c.oid) AS comment
|
|
1848
|
-
FROM pg_class c
|
|
1849
|
-
JOIN pg_catalog.pg_namespace n ON n.oid = relnamespace
|
|
1850
|
-
WHERE relkind = 'r'
|
|
1851
|
-
AND ${filterSchema("nspname")}
|
|
1852
|
-
ORDER BY relname`
|
|
1853
|
-
);
|
|
1854
|
-
return rows;
|
|
1855
|
-
}
|
|
1856
|
-
async getViews() {
|
|
1857
|
-
const { rows } = await this.db.query(
|
|
1858
|
-
`SELECT
|
|
1859
|
-
table_schema "schemaName",
|
|
1860
|
-
table_name "name"
|
|
1861
|
-
FROM information_schema.tables
|
|
1862
|
-
WHERE table_type = 'VIEW'
|
|
1863
|
-
AND ${filterSchema("table_schema")}
|
|
1864
|
-
ORDER BY table_name`
|
|
1865
|
-
);
|
|
1866
|
-
return rows;
|
|
1867
|
-
}
|
|
1868
|
-
async getProcedures() {
|
|
1869
|
-
const { rows } = await this.db.query(
|
|
1870
|
-
`SELECT
|
|
1871
|
-
n.nspname AS "schemaName",
|
|
1872
|
-
proname AS name,
|
|
1873
|
-
proretset AS "returnSet",
|
|
1874
|
-
(
|
|
1875
|
-
SELECT typname FROM pg_type WHERE oid = prorettype
|
|
1876
|
-
) AS "returnType",
|
|
1877
|
-
prokind AS "kind",
|
|
1878
|
-
coalesce((
|
|
1879
|
-
SELECT true FROM information_schema.triggers
|
|
1880
|
-
WHERE n.nspname = trigger_schema AND trigger_name = proname
|
|
1881
|
-
LIMIT 1
|
|
1882
|
-
), false) AS "isTrigger",
|
|
1883
|
-
coalesce((
|
|
1884
|
-
SELECT json_agg(pg_type.typname)
|
|
1885
|
-
FROM unnest(coalesce(proallargtypes, proargtypes)) typeId
|
|
1886
|
-
JOIN pg_type ON pg_type.oid = typeId
|
|
1887
|
-
), '[]') AS "types",
|
|
1888
|
-
coalesce(to_json(proallargtypes::int[]), to_json(proargtypes::int[])) AS "argTypes",
|
|
1889
|
-
coalesce(to_json(proargmodes), '[]') AS "argModes",
|
|
1890
|
-
to_json(proargnames) AS "argNames"
|
|
1891
|
-
FROM pg_proc p
|
|
1892
|
-
JOIN pg_namespace n ON p.pronamespace = n.oid
|
|
1893
|
-
WHERE ${filterSchema("n.nspname")}`
|
|
1894
|
-
);
|
|
1895
|
-
return rows;
|
|
1896
|
-
}
|
|
1897
|
-
async getColumns() {
|
|
1898
|
-
const { rows } = await this.db.query(
|
|
1899
|
-
`SELECT
|
|
1900
|
-
nc.nspname AS "schemaName",
|
|
1901
|
-
c.relname AS "tableName",
|
|
1911
|
+
const columnsSql = ({
|
|
1912
|
+
schema,
|
|
1913
|
+
table,
|
|
1914
|
+
join = "",
|
|
1915
|
+
where
|
|
1916
|
+
}) => `SELECT
|
|
1917
|
+
${schema}.nspname AS "schemaName",
|
|
1918
|
+
${table}.relname AS "tableName",
|
|
1902
1919
|
a.attname AS "name",
|
|
1903
1920
|
COALESCE(et.typname, t.typname) AS "type",
|
|
1904
1921
|
tn.nspname AS "typeSchema",
|
|
@@ -1956,9 +1973,8 @@ WHERE ${filterSchema("n.nspname")}`
|
|
|
1956
1973
|
) END
|
|
1957
1974
|
) "identity"
|
|
1958
1975
|
FROM pg_attribute a
|
|
1976
|
+
${join}
|
|
1959
1977
|
LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum
|
|
1960
|
-
JOIN pg_class c ON a.attrelid = c.oid
|
|
1961
|
-
JOIN pg_namespace nc ON c.relnamespace = nc.oid
|
|
1962
1978
|
JOIN pg_type t ON a.atttypid = t.oid
|
|
1963
1979
|
LEFT JOIN pg_type et ON t.typelem = et.oid
|
|
1964
1980
|
JOIN pg_namespace tn ON tn.oid = t.typnamespace
|
|
@@ -1968,12 +1984,99 @@ LEFT JOIN pg_catalog.pg_description pgd
|
|
|
1968
1984
|
ON pgd.objoid = a.attrelid
|
|
1969
1985
|
AND pgd.objsubid = a.attnum
|
|
1970
1986
|
LEFT JOIN (pg_depend dep JOIN pg_sequence seq ON (dep.classid = 'pg_class'::regclass AND dep.objid = seq.seqrelid AND dep.deptype = 'i'))
|
|
1971
|
-
ON (dep.refclassid = 'pg_class'::regclass AND dep.refobjid =
|
|
1987
|
+
ON (dep.refclassid = 'pg_class'::regclass AND dep.refobjid = ${table}.oid AND dep.refobjsubid = a.attnum)
|
|
1972
1988
|
WHERE a.attnum > 0
|
|
1973
1989
|
AND NOT a.attisdropped
|
|
1974
|
-
AND
|
|
1975
|
-
|
|
1976
|
-
|
|
1990
|
+
AND ${where}
|
|
1991
|
+
ORDER BY a.attnum`;
|
|
1992
|
+
class DbStructure {
|
|
1993
|
+
constructor(db) {
|
|
1994
|
+
this.db = db;
|
|
1995
|
+
}
|
|
1996
|
+
async getSchemas() {
|
|
1997
|
+
const { rows } = await this.db.arrays(
|
|
1998
|
+
`SELECT n.nspname "name"
|
|
1999
|
+
FROM pg_catalog.pg_namespace n
|
|
2000
|
+
WHERE ${filterSchema("n.nspname")}
|
|
2001
|
+
ORDER BY "name"`
|
|
2002
|
+
);
|
|
2003
|
+
return rows.flat();
|
|
2004
|
+
}
|
|
2005
|
+
async getTables() {
|
|
2006
|
+
const { rows } = await this.db.query(
|
|
2007
|
+
`SELECT
|
|
2008
|
+
nspname AS "schemaName",
|
|
2009
|
+
relname AS "name",
|
|
2010
|
+
obj_description(c.oid) AS comment
|
|
2011
|
+
FROM pg_class c
|
|
2012
|
+
JOIN pg_catalog.pg_namespace n ON n.oid = relnamespace
|
|
2013
|
+
WHERE relkind = 'r'
|
|
2014
|
+
AND ${filterSchema("nspname")}
|
|
2015
|
+
ORDER BY relname`
|
|
2016
|
+
);
|
|
2017
|
+
return rows;
|
|
2018
|
+
}
|
|
2019
|
+
async getViews() {
|
|
2020
|
+
const { rows } = await this.db.query(
|
|
2021
|
+
`SELECT
|
|
2022
|
+
nc.nspname AS "schemaName",
|
|
2023
|
+
c.relname AS "name",
|
|
2024
|
+
right(substring(r.ev_action from ':hasRecursive w'), 1)::bool AS "isRecursive",
|
|
2025
|
+
array_to_json(c.reloptions) AS "with",
|
|
2026
|
+
(SELECT coalesce(json_agg(t), '[]') FROM (${columnsSql({
|
|
2027
|
+
schema: "nc",
|
|
2028
|
+
table: "c",
|
|
2029
|
+
where: "a.attrelid = c.oid"
|
|
2030
|
+
})}) t) AS "columns",
|
|
2031
|
+
pg_get_viewdef(c.oid) AS "sql"
|
|
2032
|
+
FROM pg_namespace nc
|
|
2033
|
+
JOIN pg_class c
|
|
2034
|
+
ON nc.oid = c.relnamespace
|
|
2035
|
+
AND c.relkind = 'v'
|
|
2036
|
+
AND c.relpersistence != 't'
|
|
2037
|
+
JOIN pg_rewrite r ON r.ev_class = c.oid
|
|
2038
|
+
WHERE ${filterSchema("nc.nspname")}
|
|
2039
|
+
ORDER BY c.relname`
|
|
2040
|
+
);
|
|
2041
|
+
return rows;
|
|
2042
|
+
}
|
|
2043
|
+
async getProcedures() {
|
|
2044
|
+
const { rows } = await this.db.query(
|
|
2045
|
+
`SELECT
|
|
2046
|
+
n.nspname AS "schemaName",
|
|
2047
|
+
proname AS name,
|
|
2048
|
+
proretset AS "returnSet",
|
|
2049
|
+
(
|
|
2050
|
+
SELECT typname FROM pg_type WHERE oid = prorettype
|
|
2051
|
+
) AS "returnType",
|
|
2052
|
+
prokind AS "kind",
|
|
2053
|
+
coalesce((
|
|
2054
|
+
SELECT true FROM information_schema.triggers
|
|
2055
|
+
WHERE n.nspname = trigger_schema AND trigger_name = proname
|
|
2056
|
+
LIMIT 1
|
|
2057
|
+
), false) AS "isTrigger",
|
|
2058
|
+
coalesce((
|
|
2059
|
+
SELECT json_agg(pg_type.typname)
|
|
2060
|
+
FROM unnest(coalesce(proallargtypes, proargtypes)) typeId
|
|
2061
|
+
JOIN pg_type ON pg_type.oid = typeId
|
|
2062
|
+
), '[]') AS "types",
|
|
2063
|
+
coalesce(to_json(proallargtypes::int[]), to_json(proargtypes::int[])) AS "argTypes",
|
|
2064
|
+
coalesce(to_json(proargmodes), '[]') AS "argModes",
|
|
2065
|
+
to_json(proargnames) AS "argNames"
|
|
2066
|
+
FROM pg_proc p
|
|
2067
|
+
JOIN pg_namespace n ON p.pronamespace = n.oid
|
|
2068
|
+
WHERE ${filterSchema("n.nspname")}`
|
|
2069
|
+
);
|
|
2070
|
+
return rows;
|
|
2071
|
+
}
|
|
2072
|
+
async getColumns() {
|
|
2073
|
+
const { rows } = await this.db.query(
|
|
2074
|
+
columnsSql({
|
|
2075
|
+
schema: "nc",
|
|
2076
|
+
table: "c",
|
|
2077
|
+
join: `JOIN pg_class c ON a.attrelid = c.oid AND c.relkind = 'r' JOIN pg_namespace nc ON nc.oid = c.relnamespace`,
|
|
2078
|
+
where: filterSchema("nc.nspname")
|
|
2079
|
+
})
|
|
1977
2080
|
);
|
|
1978
2081
|
return rows;
|
|
1979
2082
|
}
|
|
@@ -2377,12 +2480,16 @@ const structureToAst = async (ctx, db) => {
|
|
|
2377
2480
|
tableName: fkey.tableName
|
|
2378
2481
|
}));
|
|
2379
2482
|
}
|
|
2483
|
+
for (const view of data.views) {
|
|
2484
|
+
ast.push(viewToAst(ctx, data, domains, view));
|
|
2485
|
+
}
|
|
2380
2486
|
return ast;
|
|
2381
2487
|
};
|
|
2382
2488
|
const getData = async (db) => {
|
|
2383
2489
|
const [
|
|
2384
2490
|
schemas,
|
|
2385
2491
|
tables,
|
|
2492
|
+
views,
|
|
2386
2493
|
columns,
|
|
2387
2494
|
constraints,
|
|
2388
2495
|
indexes,
|
|
@@ -2392,6 +2499,7 @@ const getData = async (db) => {
|
|
|
2392
2499
|
] = await Promise.all([
|
|
2393
2500
|
db.getSchemas(),
|
|
2394
2501
|
db.getTables(),
|
|
2502
|
+
db.getViews(),
|
|
2395
2503
|
db.getColumns(),
|
|
2396
2504
|
db.getConstraints(),
|
|
2397
2505
|
db.getIndexes(),
|
|
@@ -2402,6 +2510,7 @@ const getData = async (db) => {
|
|
|
2402
2510
|
return {
|
|
2403
2511
|
schemas,
|
|
2404
2512
|
tables,
|
|
2513
|
+
views,
|
|
2405
2514
|
columns,
|
|
2406
2515
|
constraints,
|
|
2407
2516
|
indexes,
|
|
@@ -2470,7 +2579,6 @@ const getColumnType = (type, isSerial) => {
|
|
|
2470
2579
|
return type === "int2" ? "smallserial" : type === "int4" ? "serial" : "bigserial";
|
|
2471
2580
|
};
|
|
2472
2581
|
const pushTableAst = (ctx, ast, data, domains, table, pendingTables, innerConstraints = data.constraints) => {
|
|
2473
|
-
var _a, _b;
|
|
2474
2582
|
const { schemaName, name: tableName } = table;
|
|
2475
2583
|
const key = `${schemaName}.${table.name}`;
|
|
2476
2584
|
delete pendingTables[key];
|
|
@@ -2486,7 +2594,7 @@ const pushTableAst = (ctx, ast, data, domains, table, pendingTables, innerConstr
|
|
|
2486
2594
|
const tableIndexes = data.indexes.filter(belongsToTable);
|
|
2487
2595
|
const tableConstraints = innerConstraints.reduce(
|
|
2488
2596
|
(acc, item) => {
|
|
2489
|
-
var
|
|
2597
|
+
var _a;
|
|
2490
2598
|
const { references, check } = item;
|
|
2491
2599
|
if (belongsToTable(item) && (references || check && !isColumnCheck(item))) {
|
|
2492
2600
|
const constraint = {
|
|
@@ -2505,7 +2613,7 @@ const pushTableAst = (ctx, ast, data, domains, table, pendingTables, innerConstr
|
|
|
2505
2613
|
const name = item.name && item.name !== getConstraintName(tableName, constraint) ? item.name : void 0;
|
|
2506
2614
|
if (name) {
|
|
2507
2615
|
constraint.name = name;
|
|
2508
|
-
if ((
|
|
2616
|
+
if ((_a = constraint.references) == null ? void 0 : _a.options) {
|
|
2509
2617
|
constraint.references.options.name = name;
|
|
2510
2618
|
}
|
|
2511
2619
|
}
|
|
@@ -2524,66 +2632,17 @@ const pushTableAst = (ctx, ast, data, domains, table, pendingTables, innerConstr
|
|
|
2524
2632
|
},
|
|
2525
2633
|
{}
|
|
2526
2634
|
);
|
|
2527
|
-
const shape =
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
if (item.identity) {
|
|
2539
|
-
column.data.identity = item.identity;
|
|
2540
|
-
if (!item.identity.always)
|
|
2541
|
-
(_a = column.data.identity) == null ? true : delete _a.always;
|
|
2542
|
-
}
|
|
2543
|
-
if (((_b = primaryKey == null ? void 0 : primaryKey.columns) == null ? void 0 : _b.length) === 1 && (primaryKey == null ? void 0 : primaryKey.columns[0]) === item.name) {
|
|
2544
|
-
column = column.primaryKey();
|
|
2545
|
-
}
|
|
2546
|
-
const indexes = tableIndexes.filter(
|
|
2547
|
-
(it) => it.columns.length === 1 && "column" in it.columns[0] && it.columns[0].column === item.name
|
|
2548
|
-
);
|
|
2549
|
-
for (const index of indexes) {
|
|
2550
|
-
const options = index.columns[0];
|
|
2551
|
-
column = column.index({
|
|
2552
|
-
collate: options.collate,
|
|
2553
|
-
opclass: options.opclass,
|
|
2554
|
-
order: options.order,
|
|
2555
|
-
name: index.name !== getIndexName(tableName, index.columns) ? index.name : void 0,
|
|
2556
|
-
using: index.using === "btree" ? void 0 : index.using,
|
|
2557
|
-
unique: index.isUnique,
|
|
2558
|
-
include: index.include,
|
|
2559
|
-
nullsNotDistinct: index.nullsNotDistinct,
|
|
2560
|
-
with: index.with,
|
|
2561
|
-
tablespace: index.tablespace,
|
|
2562
|
-
where: index.where
|
|
2563
|
-
});
|
|
2564
|
-
}
|
|
2565
|
-
for (const it of tableConstraints) {
|
|
2566
|
-
if (!isColumnFkey(it) || it.references.columns[0] !== item.name)
|
|
2567
|
-
continue;
|
|
2568
|
-
column = column.foreignKey(
|
|
2569
|
-
it.references.fnOrTable,
|
|
2570
|
-
it.references.foreignColumns[0],
|
|
2571
|
-
it.references.options
|
|
2572
|
-
);
|
|
2573
|
-
}
|
|
2574
|
-
const check = columnChecks[item.name];
|
|
2575
|
-
if (check) {
|
|
2576
|
-
column.data.check = orchidCore.raw(check);
|
|
2577
|
-
}
|
|
2578
|
-
const camelCaseName = orchidCore.toCamelCase(item.name);
|
|
2579
|
-
if (ctx.snakeCase) {
|
|
2580
|
-
const snakeCaseName = orchidCore.toSnakeCase(camelCaseName);
|
|
2581
|
-
column.data.name = snakeCaseName === item.name ? void 0 : item.name;
|
|
2582
|
-
} else {
|
|
2583
|
-
column.data.name = camelCaseName === item.name ? void 0 : item.name;
|
|
2584
|
-
}
|
|
2585
|
-
shape[camelCaseName] = column;
|
|
2586
|
-
}
|
|
2635
|
+
const shape = makeColumnsShape(
|
|
2636
|
+
ctx,
|
|
2637
|
+
data,
|
|
2638
|
+
domains,
|
|
2639
|
+
tableName,
|
|
2640
|
+
columns,
|
|
2641
|
+
primaryKey,
|
|
2642
|
+
tableIndexes,
|
|
2643
|
+
tableConstraints,
|
|
2644
|
+
columnChecks
|
|
2645
|
+
);
|
|
2587
2646
|
ast.push({
|
|
2588
2647
|
type: "table",
|
|
2589
2648
|
action: "create",
|
|
@@ -2670,10 +2729,101 @@ const isColumnFkey = (it) => {
|
|
|
2670
2729
|
var _a;
|
|
2671
2730
|
return !it.check && ((_a = it.references) == null ? void 0 : _a.columns.length) === 1;
|
|
2672
2731
|
};
|
|
2732
|
+
const viewToAst = (ctx, data, domains, view) => {
|
|
2733
|
+
const shape = makeColumnsShape(ctx, data, domains, view.name, view.columns);
|
|
2734
|
+
const options = {};
|
|
2735
|
+
if (view.isRecursive)
|
|
2736
|
+
options.recursive = true;
|
|
2737
|
+
if (view.with) {
|
|
2738
|
+
const withOptions = {};
|
|
2739
|
+
options.with = withOptions;
|
|
2740
|
+
for (const pair of view.with) {
|
|
2741
|
+
const [key, value] = pair.split("=");
|
|
2742
|
+
withOptions[orchidCore.toCamelCase(key)] = value === "true" ? true : value === "false" ? false : value;
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
return {
|
|
2746
|
+
type: "view",
|
|
2747
|
+
action: "create",
|
|
2748
|
+
schema: view.schemaName === "public" ? void 0 : view.schemaName,
|
|
2749
|
+
name: view.name,
|
|
2750
|
+
shape,
|
|
2751
|
+
sql: orchidCore.raw(view.sql),
|
|
2752
|
+
options
|
|
2753
|
+
};
|
|
2754
|
+
};
|
|
2755
|
+
const makeColumnsShape = (ctx, data, domains, tableName, columns, primaryKey, indexes, constraints, checks) => {
|
|
2756
|
+
var _a, _b;
|
|
2757
|
+
const shape = {};
|
|
2758
|
+
for (let item of columns) {
|
|
2759
|
+
const isSerial = getIsSerial(item);
|
|
2760
|
+
if (isSerial) {
|
|
2761
|
+
item = __spreadProps(__spreadValues({}, item), { default: void 0 });
|
|
2762
|
+
}
|
|
2763
|
+
let column = getColumn(ctx, data, domains, __spreadProps(__spreadValues({}, item), {
|
|
2764
|
+
type: item.type,
|
|
2765
|
+
isArray: item.isArray,
|
|
2766
|
+
isSerial
|
|
2767
|
+
}));
|
|
2768
|
+
if (item.identity) {
|
|
2769
|
+
column.data.identity = item.identity;
|
|
2770
|
+
if (!item.identity.always)
|
|
2771
|
+
(_a = column.data.identity) == null ? true : delete _a.always;
|
|
2772
|
+
}
|
|
2773
|
+
if (((_b = primaryKey == null ? void 0 : primaryKey.columns) == null ? void 0 : _b.length) === 1 && (primaryKey == null ? void 0 : primaryKey.columns[0]) === item.name) {
|
|
2774
|
+
column = column.primaryKey();
|
|
2775
|
+
}
|
|
2776
|
+
if (indexes) {
|
|
2777
|
+
const columnIndexes = indexes.filter(
|
|
2778
|
+
(it) => it.columns.length === 1 && "column" in it.columns[0] && it.columns[0].column === item.name
|
|
2779
|
+
);
|
|
2780
|
+
for (const index of columnIndexes) {
|
|
2781
|
+
const options = index.columns[0];
|
|
2782
|
+
column = column.index({
|
|
2783
|
+
collate: options.collate,
|
|
2784
|
+
opclass: options.opclass,
|
|
2785
|
+
order: options.order,
|
|
2786
|
+
name: index.name !== getIndexName(tableName, index.columns) ? index.name : void 0,
|
|
2787
|
+
using: index.using === "btree" ? void 0 : index.using,
|
|
2788
|
+
unique: index.isUnique,
|
|
2789
|
+
include: index.include,
|
|
2790
|
+
nullsNotDistinct: index.nullsNotDistinct,
|
|
2791
|
+
with: index.with,
|
|
2792
|
+
tablespace: index.tablespace,
|
|
2793
|
+
where: index.where
|
|
2794
|
+
});
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
if (constraints) {
|
|
2798
|
+
for (const it of constraints) {
|
|
2799
|
+
if (!isColumnFkey(it) || it.references.columns[0] !== item.name)
|
|
2800
|
+
continue;
|
|
2801
|
+
column = column.foreignKey(
|
|
2802
|
+
it.references.fnOrTable,
|
|
2803
|
+
it.references.foreignColumns[0],
|
|
2804
|
+
it.references.options
|
|
2805
|
+
);
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
const check = checks == null ? void 0 : checks[item.name];
|
|
2809
|
+
if (check) {
|
|
2810
|
+
column.data.check = orchidCore.raw(check);
|
|
2811
|
+
}
|
|
2812
|
+
const camelCaseName = orchidCore.toCamelCase(item.name);
|
|
2813
|
+
if (ctx.snakeCase) {
|
|
2814
|
+
const snakeCaseName = orchidCore.toSnakeCase(camelCaseName);
|
|
2815
|
+
column.data.name = snakeCaseName === item.name ? void 0 : item.name;
|
|
2816
|
+
} else {
|
|
2817
|
+
column.data.name = camelCaseName === item.name ? void 0 : item.name;
|
|
2818
|
+
}
|
|
2819
|
+
shape[camelCaseName] = column;
|
|
2820
|
+
}
|
|
2821
|
+
return shape;
|
|
2822
|
+
};
|
|
2673
2823
|
|
|
2674
2824
|
const astToMigration = (config, ast) => {
|
|
2675
2825
|
const first = [];
|
|
2676
|
-
const
|
|
2826
|
+
const tablesAndViews = [];
|
|
2677
2827
|
const constraints = [];
|
|
2678
2828
|
for (const item of ast) {
|
|
2679
2829
|
if (item.type === "schema" && item.action === "create") {
|
|
@@ -2691,14 +2841,16 @@ const astToMigration = (config, ast) => {
|
|
|
2691
2841
|
first.push([]);
|
|
2692
2842
|
first.push(...createDomain(item));
|
|
2693
2843
|
} else if (item.type === "table" && item.action === "create") {
|
|
2694
|
-
|
|
2844
|
+
tablesAndViews.push(createTable(config, item));
|
|
2845
|
+
} else if (item.type === "view" && item.action === "create") {
|
|
2846
|
+
tablesAndViews.push(createView(item));
|
|
2695
2847
|
} else if (item.type === "constraint") {
|
|
2696
2848
|
if (constraints.length)
|
|
2697
2849
|
constraints.push([]);
|
|
2698
2850
|
constraints.push(...createConstraint(item));
|
|
2699
2851
|
}
|
|
2700
2852
|
}
|
|
2701
|
-
if (!first.length && !
|
|
2853
|
+
if (!first.length && !tablesAndViews.length && !constraints.length)
|
|
2702
2854
|
return;
|
|
2703
2855
|
let code = `import { change } from 'rake-db';
|
|
2704
2856
|
`;
|
|
@@ -2709,8 +2861,8 @@ ${orchidCore.codeToString(first, " ", " ")}
|
|
|
2709
2861
|
});
|
|
2710
2862
|
`;
|
|
2711
2863
|
}
|
|
2712
|
-
if (
|
|
2713
|
-
for (const table of
|
|
2864
|
+
if (tablesAndViews.length) {
|
|
2865
|
+
for (const table of tablesAndViews) {
|
|
2714
2866
|
code += `
|
|
2715
2867
|
change(async (db) => {
|
|
2716
2868
|
${orchidCore.codeToString(table, " ", " ")}
|
|
@@ -2816,7 +2968,7 @@ const isTimestamp = (column) => {
|
|
|
2816
2968
|
if (!column)
|
|
2817
2969
|
return false;
|
|
2818
2970
|
const { default: def } = column.data;
|
|
2819
|
-
return column instanceof pqb.
|
|
2971
|
+
return column instanceof pqb.TimestampTzColumn && !column.data.isNullable && def && typeof def === "object" && orchidCore.isRaw(def) && def.__raw === "now()";
|
|
2820
2972
|
};
|
|
2821
2973
|
const createConstraint = (item) => {
|
|
2822
2974
|
const kind = pqb.getConstraintKind(item);
|
|
@@ -2840,6 +2992,31 @@ const createConstraint = (item) => {
|
|
|
2840
2992
|
"});"
|
|
2841
2993
|
];
|
|
2842
2994
|
};
|
|
2995
|
+
const createView = (ast) => {
|
|
2996
|
+
const code = [`await db.createView(${quoteSchemaTable(ast)}`];
|
|
2997
|
+
const options = [];
|
|
2998
|
+
if (ast.options.recursive)
|
|
2999
|
+
options.push("recursive: true,");
|
|
3000
|
+
const w = ast.options.with;
|
|
3001
|
+
if (w == null ? void 0 : w.checkOption)
|
|
3002
|
+
options.push(`checkOption: '${w.checkOption}',`);
|
|
3003
|
+
if (w == null ? void 0 : w.securityBarrier)
|
|
3004
|
+
options.push(`securityBarrier: ${w.securityBarrier},`);
|
|
3005
|
+
if (w == null ? void 0 : w.securityInvoker)
|
|
3006
|
+
options.push(`securityInvoker: ${w.securityInvoker},`);
|
|
3007
|
+
if (options.length) {
|
|
3008
|
+
orchidCore.addCode(code, ", {");
|
|
3009
|
+
code.push(options, "}");
|
|
3010
|
+
}
|
|
3011
|
+
orchidCore.addCode(code, ", ");
|
|
3012
|
+
if (!ast.sql.__values) {
|
|
3013
|
+
orchidCore.addCode(code, orchidCore.backtickQuote(ast.sql.__raw));
|
|
3014
|
+
} else {
|
|
3015
|
+
orchidCore.addCode(code, orchidCore.rawToCode("db", ast.sql));
|
|
3016
|
+
}
|
|
3017
|
+
orchidCore.addCode(code, ");");
|
|
3018
|
+
return code;
|
|
3019
|
+
};
|
|
2843
3020
|
|
|
2844
3021
|
const pullDbStructure = async (options, config) => {
|
|
2845
3022
|
var _a, _b, _c;
|