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 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$1(
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$1 = (up, tableName, shape, tableData, options, noPrimaryKey) => {
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
- class DbStructure {
1830
- constructor(db) {
1831
- this.db = db;
1832
- }
1833
- async getSchemas() {
1834
- const { rows } = await this.db.arrays(
1835
- `SELECT n.nspname "name"
1836
- FROM pg_catalog.pg_namespace n
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 = c.oid AND dep.refobjsubid = a.attnum)
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 c.relkind IN ('r', 'v', 'f', 'p')
1975
- AND ${filterSchema("nc.nspname")}
1976
- ORDER BY a.attnum`
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 _a2;
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 ((_a2 = constraint.references) == null ? void 0 : _a2.options) {
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
- for (let item of columns) {
2529
- const isSerial = getIsSerial(item);
2530
- if (isSerial) {
2531
- item = __spreadProps(__spreadValues({}, item), { default: void 0 });
2532
- }
2533
- let column = getColumn(ctx, data, domains, __spreadProps(__spreadValues({}, item), {
2534
- type: item.type,
2535
- isArray: item.isArray,
2536
- isSerial
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 tables = [];
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
- tables.push(createTable(config, item));
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 && !tables.length && !constraints.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 (tables.length) {
2713
- for (const table of tables) {
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.TimestampColumn && !column.data.isNullable && def && typeof def === "object" && orchidCore.isRaw(def) && def.__raw === "now()";
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;