Skip to content

Commit dbf1e75

Browse files
feat: add UNLOGGED support for table (#1405)
Co-authored-by: Shinigami <[email protected]>
1 parent e3d0ccf commit dbf1e75

File tree

8 files changed

+101
-15
lines changed

8 files changed

+101
-15
lines changed

docs/src/migrations/tables.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
| `constraints` | `object` | table constraints see `expression` of [add constraint](constraints.md#pgmaddconstraint-tablename-constraint_name-expression-) |
2626
| `like` | [Name](/migrations/#type) or `object` | table(s) to inherit from or object with `table` and `options` keys |
2727
| `comment` | `string` | adds comment on table |
28+
| `unlogged` | `boolean` | default `false` |
2829

2930
#### like options
3031

@@ -86,6 +87,7 @@
8687

8788
### Options
8889

89-
| Option | Type | Description |
90-
| --------------- | -------- | ------------------------------------------- |
91-
| `levelSecurity` | `string` | `DISABLE`, `ENABLE`, `FORCE`, or `NO FORCE` |
90+
| Option | Type | Description |
91+
| --------------- | --------- | ------------------------------------------- |
92+
| `levelSecurity` | `string` | `DISABLE`, `ENABLE`, `FORCE`, or `NO FORCE` |
93+
| `unlogged` | `boolean` | Sets UNLOGGED if true |

src/operations/tables/alterTable.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { formatLines } from '../../utils';
33
import type { Name } from '../generalTypes';
44

55
export interface AlterTableOptions {
6-
levelSecurity: 'DISABLE' | 'ENABLE' | 'FORCE' | 'NO FORCE';
6+
levelSecurity?: 'DISABLE' | 'ENABLE' | 'FORCE' | 'NO FORCE';
7+
unlogged?: boolean;
78
}
89

910
export type AlterTable = (
@@ -13,14 +14,20 @@ export type AlterTable = (
1314

1415
export function alterTable(mOptions: MigrationOptions): AlterTable {
1516
const _alter: AlterTable = (tableName, options) => {
16-
const { levelSecurity } = options;
17+
const { levelSecurity, unlogged } = options;
1718

1819
const alterDefinition: string[] = [];
1920

2021
if (levelSecurity) {
2122
alterDefinition.push(`${levelSecurity} ROW LEVEL SECURITY`);
2223
}
2324

25+
if (unlogged === true) {
26+
alterDefinition.push(`SET UNLOGGED`);
27+
} else if (unlogged === false) {
28+
alterDefinition.push(`SET LOGGED`);
29+
}
30+
2431
return `ALTER TABLE ${mOptions.literal(tableName)}
2532
${formatLines(alterDefinition)};`;
2633
};

src/operations/tables/createTable.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export function createTable(mOptions: MigrationOptions): CreateTable {
3333
constraints: optionsConstraints = {},
3434
comment,
3535
partition,
36+
unlogged = false,
3637
} = options;
3738

3839
const {
@@ -65,7 +66,12 @@ export function createTable(mOptions: MigrationOptions): CreateTable {
6566
...(like ? [parseLike(like, mOptions.literal)] : []),
6667
];
6768

69+
if (temporary && unlogged) {
70+
throw new Error('TEMPORARY and UNLOGGED cannot be used together.');
71+
}
72+
6873
const temporaryStr = temporary ? ' TEMPORARY' : '';
74+
const unloggedStr = unlogged ? ' UNLOGGED' : '';
6975
const ifNotExistsStr = ifNotExists ? ' IF NOT EXISTS' : '';
7076
const inheritsStr = inherits
7177
? ` INHERITS (${mOptions.literal(inherits)})`
@@ -77,7 +83,7 @@ export function createTable(mOptions: MigrationOptions): CreateTable {
7783

7884
const tableNameStr = mOptions.literal(tableName);
7985

80-
const createTableQuery = `CREATE${temporaryStr} TABLE${ifNotExistsStr} ${tableNameStr} (
86+
const createTableQuery = `CREATE${temporaryStr}${unloggedStr} TABLE${ifNotExistsStr} ${tableNameStr} (
8187
${formatLines(tableDefinition)}
8288
)${inheritsStr}${partitionStr};`;
8389
const comments = [...columnComments, ...constraintComments];

src/operations/tables/shared.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ export interface TableOptions extends IfNotExistsOption {
126126
comment?: string | null;
127127

128128
partition?: PartitionOptions;
129+
130+
unlogged?: boolean;
129131
}
130132

131133
export function parseReferences(

test/migration.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ describe('migration', () => {
6262
const filePaths = await getMigrationFilePaths(dir, { logger });
6363

6464
expect(Array.isArray(filePaths)).toBeTruthy();
65-
expect(filePaths).toHaveLength(93);
65+
expect(filePaths).toHaveLength(94);
6666
expect(filePaths).not.toContainEqual(expect.stringContaining('nested'));
6767

6868
for (const filePath of filePaths) {
@@ -83,7 +83,7 @@ describe('migration', () => {
8383
});
8484

8585
expect(Array.isArray(filePaths)).toBeTruthy();
86-
expect(filePaths).toHaveLength(68);
86+
expect(filePaths).toHaveLength(69);
8787

8888
for (const filePath of filePaths) {
8989
expect(isAbsolute(filePath)).toBeTruthy();
@@ -99,7 +99,7 @@ describe('migration', () => {
9999
});
100100

101101
expect(Array.isArray(filePaths)).toBeTruthy();
102-
expect(filePaths).toHaveLength(106);
102+
expect(filePaths).toHaveLength(107);
103103
expect(filePaths).toContainEqual(expect.stringContaining('nested'));
104104

105105
for (const filePath of filePaths) {
@@ -119,7 +119,7 @@ describe('migration', () => {
119119
});
120120

121121
expect(Array.isArray(filePaths)).toBeTruthy();
122-
expect(filePaths).toHaveLength(105);
122+
expect(filePaths).toHaveLength(106);
123123
expect(filePaths).toContainEqual(expect.stringContaining('nested'));
124124

125125
for (const filePath of filePaths) {

test/migrations/094_unlogged_table.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
export const comment = 'comment on unlogged table t_unlogged';
2+
3+
export const up = (pgm) => {
4+
// Create an unlogged table
5+
pgm.createTable(
6+
't_unlogged',
7+
{
8+
id: 'id',
9+
name: { type: 'text', notNull: true },
10+
created_at: {
11+
type: 'timestamp',
12+
notNull: true,
13+
default: pgm.func('current_timestamp'),
14+
},
15+
},
16+
{
17+
unlogged: true, // Specify the table as UNLOGGED
18+
comment,
19+
}
20+
);
21+
22+
// Create a regular table for comparison
23+
pgm.createTable(
24+
't_regular',
25+
{
26+
id: 'id',
27+
description: { type: 'text', notNull: true },
28+
},
29+
{
30+
comment: 'comment on regular table t_regular',
31+
}
32+
);
33+
34+
// Alter the regular table to set it as LOGGED
35+
pgm.alterTable('t_regular', {
36+
unlogged: false,
37+
});
38+
};
39+
40+
export const down = (pgm) => {
41+
pgm.dropTable('t_unlogged');
42+
pgm.dropTable('t_regular');
43+
};

test/operations/tables/alterTable.spec.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,7 @@ describe('operations', () => {
1313

1414
// TODO @Shinigami92 2024-03-11: This should throw an error
1515
it('should return sql statement', () => {
16-
const statement = alterTableFn(
17-
'films',
18-
// @ts-expect-error: add runtime error
19-
{}
20-
);
16+
const statement = alterTableFn('films', {});
2117

2218
expect(statement).toBeTypeOf('string');
2319
expect(statement).toBe(`ALTER TABLE "films"
@@ -33,6 +29,26 @@ describe('operations', () => {
3329
expect(statement).toBe(`ALTER TABLE "distributors"
3430
ENABLE ROW LEVEL SECURITY;`);
3531
});
32+
33+
it('should generate SQL for SET LOGGED', () => {
34+
const statement = alterTableFn('my_table', {
35+
unlogged: false,
36+
});
37+
38+
expect(statement).toBeTypeOf('string');
39+
expect(statement).toBe(`ALTER TABLE "my_table"
40+
SET LOGGED;`);
41+
});
42+
43+
it('should generate SQL for SET UNLOGGED', () => {
44+
const statement = alterTableFn('my_table', {
45+
unlogged: true,
46+
});
47+
48+
expect(statement).toBeTypeOf('string');
49+
expect(statement).toBe(`ALTER TABLE "my_table"
50+
SET UNLOGGED;`);
51+
});
3652
});
3753
});
3854
});

test/operations/tables/createTable.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,16 @@ COMMENT ON CONSTRAINT "fk_col_b" ON "my_table_name" IS $pga$fk b comment$pga$;`,
708708
],
709709
new Error('cannot comment on unspecified constraints'),
710710
],
711+
[
712+
'should throw on using both temporary and unlogged options',
713+
options1,
714+
[
715+
'myTableName',
716+
{ colA: { type: 'integer' } },
717+
{ temporary: true, unlogged: true },
718+
],
719+
new Error('TEMPORARY and UNLOGGED cannot be used together.'),
720+
],
711721
] as const)(
712722
'%s',
713723
(_, optionPreset, [tableName, columns, options], expected) => {

0 commit comments

Comments
 (0)