durcno 1.0.0-alpha.0
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/LICENSE +201 -0
- package/README.md +56 -0
- package/dist/bin.cjs +13522 -0
- package/dist/src/_virtual/_rolldown/runtime.mjs +28 -0
- package/dist/src/cli/helpers.mjs +16 -0
- package/dist/src/columns/bigint.d.mts +19 -0
- package/dist/src/columns/bigint.mjs +32 -0
- package/dist/src/columns/bigserial.d.mts +24 -0
- package/dist/src/columns/bigserial.mjs +35 -0
- package/dist/src/columns/boolean.d.mts +19 -0
- package/dist/src/columns/boolean.mjs +31 -0
- package/dist/src/columns/bytea.d.mts +19 -0
- package/dist/src/columns/bytea.mjs +33 -0
- package/dist/src/columns/char.d.mts +32 -0
- package/dist/src/columns/char.mjs +44 -0
- package/dist/src/columns/cidr.d.mts +19 -0
- package/dist/src/columns/cidr.mjs +31 -0
- package/dist/src/columns/common.d.mts +233 -0
- package/dist/src/columns/common.mjs +276 -0
- package/dist/src/columns/date.d.mts +19 -0
- package/dist/src/columns/date.mjs +32 -0
- package/dist/src/columns/enum.d.mts +21 -0
- package/dist/src/columns/enum.mjs +35 -0
- package/dist/src/columns/inet.d.mts +19 -0
- package/dist/src/columns/inet.mjs +36 -0
- package/dist/src/columns/integer.d.mts +19 -0
- package/dist/src/columns/integer.mjs +32 -0
- package/dist/src/columns/json.d.mts +52 -0
- package/dist/src/columns/json.mjs +67 -0
- package/dist/src/columns/jsonb.d.mts +53 -0
- package/dist/src/columns/jsonb.mjs +68 -0
- package/dist/src/columns/macaddr.d.mts +19 -0
- package/dist/src/columns/macaddr.mjs +31 -0
- package/dist/src/columns/numeric.d.mts +42 -0
- package/dist/src/columns/numeric.mjs +57 -0
- package/dist/src/columns/postgis/geography/index.d.mts +18 -0
- package/dist/src/columns/postgis/geography/index.mjs +17 -0
- package/dist/src/columns/postgis/geography/linestring.d.mts +38 -0
- package/dist/src/columns/postgis/geography/linestring.mjs +70 -0
- package/dist/src/columns/postgis/geography/multilinestring.d.mts +39 -0
- package/dist/src/columns/postgis/geography/multilinestring.mjs +70 -0
- package/dist/src/columns/postgis/geography/multipoint.d.mts +38 -0
- package/dist/src/columns/postgis/geography/multipoint.mjs +70 -0
- package/dist/src/columns/postgis/geography/multipolygon.d.mts +40 -0
- package/dist/src/columns/postgis/geography/multipolygon.mjs +70 -0
- package/dist/src/columns/postgis/geography/point.d.mts +36 -0
- package/dist/src/columns/postgis/geography/point.mjs +69 -0
- package/dist/src/columns/postgis/geography/polygon.d.mts +39 -0
- package/dist/src/columns/postgis/geography/polygon.mjs +70 -0
- package/dist/src/columns/serial.d.mts +24 -0
- package/dist/src/columns/serial.mjs +35 -0
- package/dist/src/columns/smallint.d.mts +19 -0
- package/dist/src/columns/smallint.mjs +32 -0
- package/dist/src/columns/smallserial.d.mts +24 -0
- package/dist/src/columns/smallserial.mjs +35 -0
- package/dist/src/columns/text.d.mts +19 -0
- package/dist/src/columns/text.mjs +30 -0
- package/dist/src/columns/time.d.mts +44 -0
- package/dist/src/columns/time.mjs +47 -0
- package/dist/src/columns/timestamp.d.mts +44 -0
- package/dist/src/columns/timestamp.mjs +47 -0
- package/dist/src/columns/uuid.d.mts +33 -0
- package/dist/src/columns/uuid.mjs +44 -0
- package/dist/src/columns/varchar.d.mts +32 -0
- package/dist/src/columns/varchar.mjs +44 -0
- package/dist/src/connectors/bun.d.mts +18 -0
- package/dist/src/connectors/bun.mjs +97 -0
- package/dist/src/connectors/common.d.mts +148 -0
- package/dist/src/connectors/common.mjs +65 -0
- package/dist/src/connectors/pg.d.mts +18 -0
- package/dist/src/connectors/pg.mjs +103 -0
- package/dist/src/connectors/pglite.d.mts +19 -0
- package/dist/src/connectors/pglite.mjs +94 -0
- package/dist/src/connectors/postgres.d.mts +18 -0
- package/dist/src/connectors/postgres.mjs +93 -0
- package/dist/src/constraints/check.d.mts +88 -0
- package/dist/src/constraints/check.mjs +307 -0
- package/dist/src/constraints/primary-key.d.mts +28 -0
- package/dist/src/constraints/primary-key.mjs +36 -0
- package/dist/src/constraints/unique.d.mts +28 -0
- package/dist/src/constraints/unique.mjs +36 -0
- package/dist/src/db.d.mts +180 -0
- package/dist/src/db.mjs +191 -0
- package/dist/src/entity.mjs +23 -0
- package/dist/src/enumtype.d.mts +27 -0
- package/dist/src/enumtype.mjs +42 -0
- package/dist/src/filters/array.d.mts +97 -0
- package/dist/src/filters/array.mjs +150 -0
- package/dist/src/filters/custom.d.mts +12 -0
- package/dist/src/filters/custom.mjs +7 -0
- package/dist/src/filters/index.d.mts +155 -0
- package/dist/src/filters/index.mjs +318 -0
- package/dist/src/functions/index.d.mts +24 -0
- package/dist/src/functions/index.mjs +29 -0
- package/dist/src/index.d.mts +129 -0
- package/dist/src/index.mjs +78 -0
- package/dist/src/indexes.d.mts +31 -0
- package/dist/src/indexes.mjs +43 -0
- package/dist/src/migration/consts.d.mts +8 -0
- package/dist/src/migration/consts.mjs +8 -0
- package/dist/src/migration/ddl.d.mts +747 -0
- package/dist/src/migration/ddl.mjs +1084 -0
- package/dist/src/migration/index.d.mts +15 -0
- package/dist/src/migration/index.mjs +5 -0
- package/dist/src/migration/snapshot.d.mts +169 -0
- package/dist/src/migration/snapshot.mjs +123 -0
- package/dist/src/migration/statement.d.mts +89 -0
- package/dist/src/migration/statement.mjs +61 -0
- package/dist/src/models.d.mts +34 -0
- package/dist/src/models.mjs +27 -0
- package/dist/src/node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/index.mjs +126 -0
- package/dist/src/node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/utilities.mjs +29 -0
- package/dist/src/node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.mjs +165 -0
- package/dist/src/node_modules/.pnpm/chalk@5.6.2/node_modules/chalk/source/vendor/supports-color/index.mjs +92 -0
- package/dist/src/query-builders/aggregates.d.mts +20 -0
- package/dist/src/query-builders/aggregates.mjs +43 -0
- package/dist/src/query-builders/count.d.mts +19 -0
- package/dist/src/query-builders/count.mjs +36 -0
- package/dist/src/query-builders/delete.d.mts +19 -0
- package/dist/src/query-builders/delete.mjs +57 -0
- package/dist/src/query-builders/distinct.d.mts +19 -0
- package/dist/src/query-builders/distinct.mjs +42 -0
- package/dist/src/query-builders/exists.d.mts +19 -0
- package/dist/src/query-builders/exists.mjs +37 -0
- package/dist/src/query-builders/first.d.mts +17 -0
- package/dist/src/query-builders/first.mjs +46 -0
- package/dist/src/query-builders/insert-returning.d.mts +16 -0
- package/dist/src/query-builders/insert-returning.mjs +63 -0
- package/dist/src/query-builders/insert.d.mts +22 -0
- package/dist/src/query-builders/insert.mjs +93 -0
- package/dist/src/query-builders/orderby-clause.d.mts +14 -0
- package/dist/src/query-builders/orderby-clause.mjs +20 -0
- package/dist/src/query-builders/pre.d.mts +36 -0
- package/dist/src/query-builders/pre.mjs +60 -0
- package/dist/src/query-builders/query-promise.d.mts +14 -0
- package/dist/src/query-builders/query-promise.mjs +21 -0
- package/dist/src/query-builders/query.d.mts +14 -0
- package/dist/src/query-builders/query.mjs +17 -0
- package/dist/src/query-builders/raw.d.mts +14 -0
- package/dist/src/query-builders/raw.mjs +26 -0
- package/dist/src/query-builders/rq.d.mts +36 -0
- package/dist/src/query-builders/rq.mjs +231 -0
- package/dist/src/query-builders/select.d.mts +48 -0
- package/dist/src/query-builders/select.mjs +118 -0
- package/dist/src/query-builders/update.d.mts +24 -0
- package/dist/src/query-builders/update.mjs +99 -0
- package/dist/src/sequence.d.mts +48 -0
- package/dist/src/sequence.mjs +53 -0
- package/dist/src/sql.d.mts +15 -0
- package/dist/src/sql.mjs +36 -0
- package/dist/src/symbols.d.mts +4 -0
- package/dist/src/symbols.mjs +4 -0
- package/dist/src/table.d.mts +144 -0
- package/dist/src/table.mjs +134 -0
- package/dist/src/types.d.mts +4 -0
- package/dist/src/utils.mjs +10 -0
- package/dist/src/validators/zod.d.mts +23 -0
- package/dist/src/validators/zod.mjs +27 -0
- package/dist/src/wkx/binaryreader.mjs +56 -0
- package/dist/src/wkx/binarywriter.mjs +110 -0
- package/dist/src/wkx/geometry.mjs +101 -0
- package/dist/src/wkx/geometrycollection.mjs +113 -0
- package/dist/src/wkx/index.mjs +18 -0
- package/dist/src/wkx/linestring.mjs +124 -0
- package/dist/src/wkx/multilinestring.mjs +133 -0
- package/dist/src/wkx/multipoint.mjs +120 -0
- package/dist/src/wkx/multipolygon.mjs +155 -0
- package/dist/src/wkx/parser.mjs +183 -0
- package/dist/src/wkx/point.mjs +159 -0
- package/dist/src/wkx/polygon.mjs +189 -0
- package/dist/src/wkx/types.mjs +37 -0
- package/dist/src/wkx/wktparser.mjs +109 -0
- package/dist/src/wkx/zigzag.mjs +18 -0
- package/package.json +100 -0
|
@@ -0,0 +1,1084 @@
|
|
|
1
|
+
import { snapshotExprToSQL } from "../constraints/check.mjs";
|
|
2
|
+
import { CustomStatement, DDLStatement } from "./statement.mjs";
|
|
3
|
+
//#region src/migration/ddl.ts
|
|
4
|
+
/**
|
|
5
|
+
* Builds a quoted relation name from schema and name.
|
|
6
|
+
* Examples:
|
|
7
|
+
* - schema="public", name="users" -> "public"."users"
|
|
8
|
+
*/
|
|
9
|
+
function buildRelation(schema, name) {
|
|
10
|
+
return `"${schema}"."${name}"`;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* DDL statement that creates a new PostgreSQL schema.
|
|
14
|
+
*
|
|
15
|
+
* Generates: `CREATE SCHEMA <name>;`
|
|
16
|
+
*
|
|
17
|
+
* @remarks
|
|
18
|
+
* Schemas are not tracked in the migration snapshot.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* ddl.createSchema('analytics');
|
|
23
|
+
* // CREATE SCHEMA analytics;
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
var CreateSchemaStatement = class extends DDLStatement {
|
|
27
|
+
type = "createSchema";
|
|
28
|
+
/**
|
|
29
|
+
* @param schema - The name of the schema to create.
|
|
30
|
+
*/
|
|
31
|
+
constructor(schema) {
|
|
32
|
+
super();
|
|
33
|
+
this.schema = schema;
|
|
34
|
+
}
|
|
35
|
+
toSQL() {
|
|
36
|
+
return `CREATE SCHEMA ${this.schema};`;
|
|
37
|
+
}
|
|
38
|
+
/** Schemas are not tracked in snapshot, so this is a no-op. */
|
|
39
|
+
applyToSnapshot(_snapshot) {}
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* DDL statement that drops an existing PostgreSQL schema.
|
|
43
|
+
*
|
|
44
|
+
* Generates: `DROP SCHEMA <name>;`
|
|
45
|
+
*
|
|
46
|
+
* @remarks
|
|
47
|
+
* Schemas are not tracked in the migration snapshot.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* ddl.dropSchema('analytics');
|
|
52
|
+
* // DROP SCHEMA analytics;
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
var DropSchemaStatement = class extends DDLStatement {
|
|
56
|
+
type = "dropSchema";
|
|
57
|
+
/**
|
|
58
|
+
* @param schema - The name of the schema to drop.
|
|
59
|
+
*/
|
|
60
|
+
constructor(schema) {
|
|
61
|
+
super();
|
|
62
|
+
this.schema = schema;
|
|
63
|
+
}
|
|
64
|
+
toSQL() {
|
|
65
|
+
return `DROP SCHEMA ${this.schema};`;
|
|
66
|
+
}
|
|
67
|
+
/** Schemas are not tracked in snapshot, so this is a no-op. */
|
|
68
|
+
applyToSnapshot(_snapshot) {}
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* DDL statement that creates a new PostgreSQL enum type.
|
|
72
|
+
*
|
|
73
|
+
* Generates: `CREATE TYPE "schema"."name" AS ENUM('val1', 'val2', ...);`
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* ddl.createEnum('public', 'user_type', ['admin', 'user', 'guest']);
|
|
78
|
+
* // CREATE TYPE "public"."user_type" AS ENUM('admin', 'user', 'guest');
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
var CreateEnumStatement = class extends DDLStatement {
|
|
82
|
+
type = "createEnum";
|
|
83
|
+
/**
|
|
84
|
+
* @param schema - The schema the enum belongs to.
|
|
85
|
+
* @param name - The name of the enum type to create.
|
|
86
|
+
* @param values - Ordered list of allowed enum values.
|
|
87
|
+
*/
|
|
88
|
+
constructor(schema, name, values) {
|
|
89
|
+
super();
|
|
90
|
+
this.schema = schema;
|
|
91
|
+
this.name = name;
|
|
92
|
+
this.values = values;
|
|
93
|
+
}
|
|
94
|
+
toSQL() {
|
|
95
|
+
return `CREATE TYPE ${buildRelation(this.schema, this.name)} AS ENUM(${this.values.map((v) => `'${v}'`).join(", ")});`;
|
|
96
|
+
}
|
|
97
|
+
applyToSnapshot(snapshot) {
|
|
98
|
+
const key = `${this.schema}.${this.name}`;
|
|
99
|
+
snapshot.enums[key] = {
|
|
100
|
+
schema: this.schema,
|
|
101
|
+
name: this.name,
|
|
102
|
+
values: [...this.values]
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* DDL statement that adds a value to an existing PostgreSQL enum type.
|
|
108
|
+
*
|
|
109
|
+
* Generates: `ALTER TYPE "schema"."name" ADD VALUE IF NOT EXISTS 'value' [AFTER|BEFORE 'ref'];`
|
|
110
|
+
*
|
|
111
|
+
* @remarks
|
|
112
|
+
* PostgreSQL does not support removing values from an enum.
|
|
113
|
+
* Values can only be added, optionally positioned relative to an existing value.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* // Append a value
|
|
118
|
+
* ddl.alterEnumAddValue('public', 'user_type', 'moderator');
|
|
119
|
+
*
|
|
120
|
+
* // Insert after a specific value
|
|
121
|
+
* ddl.alterEnumAddValue('public', 'user_type', 'moderator', { after: 'admin' });
|
|
122
|
+
*
|
|
123
|
+
* // Insert before a specific value
|
|
124
|
+
* ddl.alterEnumAddValue('public', 'user_type', 'moderator', { before: 'user' });
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
var AlterEnumAddValueStatement = class extends DDLStatement {
|
|
128
|
+
type = "alterEnum";
|
|
129
|
+
/**
|
|
130
|
+
* @param schema - The schema the enum belongs to.
|
|
131
|
+
* @param name - The enum type name.
|
|
132
|
+
* @param value - The new value to add.
|
|
133
|
+
* @param position - Optional positioning: `{ after: 'val' }` or `{ before: 'val' }`.
|
|
134
|
+
*/
|
|
135
|
+
constructor(schema, name, value, position) {
|
|
136
|
+
super();
|
|
137
|
+
this.schema = schema;
|
|
138
|
+
this.name = name;
|
|
139
|
+
this.value = value;
|
|
140
|
+
this.position = position;
|
|
141
|
+
}
|
|
142
|
+
toSQL() {
|
|
143
|
+
let sql = `ALTER TYPE ${buildRelation(this.schema, this.name)} ADD VALUE IF NOT EXISTS '${this.value}'`;
|
|
144
|
+
if (this.position?.after) sql += ` AFTER '${this.position.after}'`;
|
|
145
|
+
else if (this.position?.before) sql += ` BEFORE '${this.position.before}'`;
|
|
146
|
+
return `${sql};`;
|
|
147
|
+
}
|
|
148
|
+
applyToSnapshot(snapshot) {
|
|
149
|
+
const key = `${this.schema}.${this.name}`;
|
|
150
|
+
const enm = snapshot.enums[key];
|
|
151
|
+
if (!enm) return;
|
|
152
|
+
if (this.position?.after) {
|
|
153
|
+
const afterIdx = enm.values.indexOf(this.position.after);
|
|
154
|
+
if (afterIdx !== -1) {
|
|
155
|
+
enm.values.splice(afterIdx + 1, 0, this.value);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
} else if (this.position?.before) {
|
|
159
|
+
const beforeIdx = enm.values.indexOf(this.position.before);
|
|
160
|
+
if (beforeIdx !== -1) {
|
|
161
|
+
enm.values.splice(beforeIdx, 0, this.value);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
enm.values.push(this.value);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
/**
|
|
169
|
+
* DDL statement that drops an existing PostgreSQL enum type.
|
|
170
|
+
*
|
|
171
|
+
* Generates: `DROP TYPE "schema"."name";`
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* ddl.dropEnum('public', 'user_type');
|
|
176
|
+
* // DROP TYPE "public"."user_type";
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
var DropEnumStatement = class extends DDLStatement {
|
|
180
|
+
type = "dropEnum";
|
|
181
|
+
/**
|
|
182
|
+
* @param schema - The schema the enum belongs to.
|
|
183
|
+
* @param name - The enum type name to drop.
|
|
184
|
+
*/
|
|
185
|
+
constructor(schema, name) {
|
|
186
|
+
super();
|
|
187
|
+
this.schema = schema;
|
|
188
|
+
this.name = name;
|
|
189
|
+
}
|
|
190
|
+
toSQL() {
|
|
191
|
+
return `DROP TYPE ${buildRelation(this.schema, this.name)};`;
|
|
192
|
+
}
|
|
193
|
+
applyToSnapshot(snapshot) {
|
|
194
|
+
const key = `${this.schema}.${this.name}`;
|
|
195
|
+
delete snapshot.enums[key];
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* DDL statement that creates a new PostgreSQL sequence.
|
|
200
|
+
*
|
|
201
|
+
* Generates: `CREATE SEQUENCE "schema"."name" [START WITH n] [INCREMENT BY n] ...;`
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```typescript
|
|
205
|
+
* ddl.createSequence('public', 'order_seq', {
|
|
206
|
+
* startWith: 1000,
|
|
207
|
+
* increment: 1,
|
|
208
|
+
* cache: 10,
|
|
209
|
+
* });
|
|
210
|
+
* // CREATE SEQUENCE "public"."order_seq" START WITH 1000 INCREMENT BY 1 CACHE 10;
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
var CreateSequenceStatement = class extends DDLStatement {
|
|
214
|
+
type = "createSequence";
|
|
215
|
+
/**
|
|
216
|
+
* @param schema - The schema the sequence belongs to.
|
|
217
|
+
* @param name - The sequence name.
|
|
218
|
+
* @param options - Optional sequence configuration.
|
|
219
|
+
*/
|
|
220
|
+
constructor(schema, name, options = {}) {
|
|
221
|
+
super();
|
|
222
|
+
this.schema = schema;
|
|
223
|
+
this.name = name;
|
|
224
|
+
this.options = options;
|
|
225
|
+
}
|
|
226
|
+
toSQL() {
|
|
227
|
+
let sql = `CREATE SEQUENCE ${buildRelation(this.schema, this.name)}`;
|
|
228
|
+
if (this.options.startWith !== void 0) sql += ` START WITH ${this.options.startWith}`;
|
|
229
|
+
if (this.options.increment !== void 0) sql += ` INCREMENT BY ${this.options.increment}`;
|
|
230
|
+
if (this.options.minValue !== void 0) sql += ` MINVALUE ${this.options.minValue}`;
|
|
231
|
+
if (this.options.maxValue !== void 0) sql += ` MAXVALUE ${this.options.maxValue}`;
|
|
232
|
+
if (this.options.cycle) sql += " CYCLE";
|
|
233
|
+
if (this.options.cache !== void 0) sql += ` CACHE ${this.options.cache}`;
|
|
234
|
+
return `${sql};`;
|
|
235
|
+
}
|
|
236
|
+
applyToSnapshot(snapshot) {
|
|
237
|
+
const key = `${this.schema}.${this.name}`;
|
|
238
|
+
snapshot.sequences[key] = {
|
|
239
|
+
schema: this.schema,
|
|
240
|
+
name: this.name,
|
|
241
|
+
startWith: this.options.startWith,
|
|
242
|
+
increment: this.options.increment,
|
|
243
|
+
minValue: this.options.minValue,
|
|
244
|
+
maxValue: this.options.maxValue,
|
|
245
|
+
cycle: this.options.cycle,
|
|
246
|
+
cache: this.options.cache
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
/**
|
|
251
|
+
* DDL statement that drops an existing PostgreSQL sequence.
|
|
252
|
+
*
|
|
253
|
+
* Generates: `DROP SEQUENCE "schema"."name";`
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```typescript
|
|
257
|
+
* ddl.dropSequence('public', 'order_seq');
|
|
258
|
+
* // DROP SEQUENCE "public"."order_seq";
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
var DropSequenceStatement = class extends DDLStatement {
|
|
262
|
+
type = "dropSequence";
|
|
263
|
+
/**
|
|
264
|
+
* @param schema - The schema the sequence belongs to.
|
|
265
|
+
* @param name - The sequence name to drop.
|
|
266
|
+
*/
|
|
267
|
+
constructor(schema, name) {
|
|
268
|
+
super();
|
|
269
|
+
this.schema = schema;
|
|
270
|
+
this.name = name;
|
|
271
|
+
}
|
|
272
|
+
toSQL() {
|
|
273
|
+
return `DROP SEQUENCE ${buildRelation(this.schema, this.name)};`;
|
|
274
|
+
}
|
|
275
|
+
applyToSnapshot(snapshot) {
|
|
276
|
+
const key = `${this.schema}.${this.name}`;
|
|
277
|
+
delete snapshot.sequences[key];
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* Generates a SQL column definition string from column metadata.
|
|
282
|
+
* Used by both CREATE TABLE and ALTER TABLE statements.
|
|
283
|
+
*/
|
|
284
|
+
function toColumnDef(name, type, options = {}) {
|
|
285
|
+
let def = `"${name}" ${type}`;
|
|
286
|
+
if (options.primaryKey) def += " PRIMARY KEY";
|
|
287
|
+
if (options.references) {
|
|
288
|
+
const refTable = `"${options.references.schema}"."${options.references.table}"`;
|
|
289
|
+
def += ` REFERENCES ${refTable}(${options.references.column}) ON DELETE ${options.references.onDelete}`;
|
|
290
|
+
}
|
|
291
|
+
if (options.unique) def += " UNIQUE";
|
|
292
|
+
if (options.notNull) def += " NOT NULL";
|
|
293
|
+
if (options.default !== void 0) def += ` DEFAULT ${options.default}`;
|
|
294
|
+
if (options.generated) def += ` GENERATED ${options.generated} AS ${options.as}`;
|
|
295
|
+
return def;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Chainable builder that constructs a `CREATE TABLE` DDL statement.
|
|
299
|
+
*
|
|
300
|
+
* Use {@link ddl.createTable} to obtain an instance, then chain
|
|
301
|
+
* `.column()`, `.check()`, `.uniqueConstraint()`, and `.primaryKeyConstraint()`.
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* ```typescript
|
|
305
|
+
* ddl.createTable('public', 'users')
|
|
306
|
+
* .column('id', 'serial', { primaryKey: true })
|
|
307
|
+
* .column('name', 'varchar(255)', { notNull: true })
|
|
308
|
+
* .column('email', 'varchar(255)', { notNull: true, unique: true })
|
|
309
|
+
* .check('name_length', { column: 'name', op: '>', value: 0 })
|
|
310
|
+
* .uniqueConstraint('users_name_email_unique', ['name', 'email']);
|
|
311
|
+
* ```
|
|
312
|
+
*/
|
|
313
|
+
var CreateTableBuilder = class extends DDLStatement {
|
|
314
|
+
type = "createTable";
|
|
315
|
+
columns = [];
|
|
316
|
+
checks = [];
|
|
317
|
+
_uniqueConstraints = [];
|
|
318
|
+
_primaryKeyConstraint;
|
|
319
|
+
/**
|
|
320
|
+
* @param schema - The PostgreSQL schema to create the table in.
|
|
321
|
+
* @param name - The table name.
|
|
322
|
+
*/
|
|
323
|
+
constructor(schema, name) {
|
|
324
|
+
super();
|
|
325
|
+
this.schema = schema;
|
|
326
|
+
this.name = name;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Add a column to the table.
|
|
330
|
+
*
|
|
331
|
+
* @param colName - Column name.
|
|
332
|
+
* @param type - SQL type (e.g. `"varchar(255)"`, `"integer"`, `"serial"`).
|
|
333
|
+
* @param options - Column options (constraints, default, references, etc.).
|
|
334
|
+
* @returns `this` for chaining.
|
|
335
|
+
*/
|
|
336
|
+
column(colName, type, options = {}) {
|
|
337
|
+
this.columns.push({
|
|
338
|
+
name: colName,
|
|
339
|
+
type,
|
|
340
|
+
options
|
|
341
|
+
});
|
|
342
|
+
return this;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Add a CHECK constraint to the table.
|
|
346
|
+
*
|
|
347
|
+
* @param chkName - Constraint name.
|
|
348
|
+
* @param expr - The check expression.
|
|
349
|
+
* @returns `this` for chaining.
|
|
350
|
+
*/
|
|
351
|
+
check(chkName, expr) {
|
|
352
|
+
this.checks.push({
|
|
353
|
+
name: chkName,
|
|
354
|
+
expr
|
|
355
|
+
});
|
|
356
|
+
return this;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Add a table-level UNIQUE constraint spanning one or more columns.
|
|
360
|
+
*
|
|
361
|
+
* @param ucName - Constraint name.
|
|
362
|
+
* @param columns - Column names that form the unique key.
|
|
363
|
+
* @returns `this` for chaining.
|
|
364
|
+
*/
|
|
365
|
+
uniqueConstraint(ucName, columns) {
|
|
366
|
+
this._uniqueConstraints.push({
|
|
367
|
+
name: ucName,
|
|
368
|
+
columns
|
|
369
|
+
});
|
|
370
|
+
return this;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Add a composite PRIMARY KEY constraint.
|
|
374
|
+
*
|
|
375
|
+
* @param pkName - Constraint name.
|
|
376
|
+
* @param columns - Column names that form the primary key.
|
|
377
|
+
* @returns `this` for chaining.
|
|
378
|
+
*/
|
|
379
|
+
primaryKeyConstraint(pkName, columns) {
|
|
380
|
+
this._primaryKeyConstraint = {
|
|
381
|
+
name: pkName,
|
|
382
|
+
columns
|
|
383
|
+
};
|
|
384
|
+
return this;
|
|
385
|
+
}
|
|
386
|
+
toSQL() {
|
|
387
|
+
const relation = buildRelation(this.schema, this.name);
|
|
388
|
+
const entries = [];
|
|
389
|
+
for (const col of this.columns) entries.push(` ${toColumnDef(col.name, col.type, col.options)}`);
|
|
390
|
+
for (const chk of this.checks) entries.push(` CONSTRAINT ${chk.name} CHECK (${snapshotExprToSQL(chk.expr)})`);
|
|
391
|
+
for (const uc of this._uniqueConstraints) {
|
|
392
|
+
const cols = uc.columns.map((c) => `"${c}"`).join(", ");
|
|
393
|
+
entries.push(` CONSTRAINT ${uc.name} UNIQUE (${cols})`);
|
|
394
|
+
}
|
|
395
|
+
if (this._primaryKeyConstraint) {
|
|
396
|
+
const pk = this._primaryKeyConstraint;
|
|
397
|
+
const cols = pk.columns.map((c) => `"${c}"`).join(", ");
|
|
398
|
+
entries.push(` CONSTRAINT ${pk.name} PRIMARY KEY (${cols})`);
|
|
399
|
+
}
|
|
400
|
+
return `CREATE TABLE ${relation} (\n${entries.join(",\n")}\n);`;
|
|
401
|
+
}
|
|
402
|
+
applyToSnapshot(snapshot) {
|
|
403
|
+
const key = `${this.schema}.${this.name}`;
|
|
404
|
+
const columns = {};
|
|
405
|
+
for (const col of this.columns) {
|
|
406
|
+
const colSnapshot = { type: col.type };
|
|
407
|
+
if (col.options.notNull) colSnapshot.notNull = true;
|
|
408
|
+
if (col.options.primaryKey) colSnapshot.primaryKey = true;
|
|
409
|
+
if (col.options.unique) colSnapshot.unique = true;
|
|
410
|
+
if (col.options.default !== void 0) colSnapshot.default = col.options.default;
|
|
411
|
+
if (col.options.generated) colSnapshot.generated = col.options.generated;
|
|
412
|
+
if (col.options.as) colSnapshot.as = col.options.as;
|
|
413
|
+
if (col.options.references) colSnapshot.references = {
|
|
414
|
+
schema: col.options.references.schema,
|
|
415
|
+
table: col.options.references.table,
|
|
416
|
+
column: col.options.references.column,
|
|
417
|
+
onDelete: col.options.references.onDelete
|
|
418
|
+
};
|
|
419
|
+
columns[col.name] = colSnapshot;
|
|
420
|
+
}
|
|
421
|
+
const tableKey = `${this.schema}.${this.name}`;
|
|
422
|
+
const checks = {};
|
|
423
|
+
for (const chk of this.checks) checks[chk.name] = {
|
|
424
|
+
name: chk.name,
|
|
425
|
+
table: tableKey,
|
|
426
|
+
expr: chk.expr
|
|
427
|
+
};
|
|
428
|
+
const uniqueConstraints = {};
|
|
429
|
+
for (const uc of this._uniqueConstraints) uniqueConstraints[uc.name] = {
|
|
430
|
+
name: uc.name,
|
|
431
|
+
table: tableKey,
|
|
432
|
+
columns: [...uc.columns]
|
|
433
|
+
};
|
|
434
|
+
let primaryKeyConstraint;
|
|
435
|
+
if (this._primaryKeyConstraint) primaryKeyConstraint = {
|
|
436
|
+
name: this._primaryKeyConstraint.name,
|
|
437
|
+
table: tableKey,
|
|
438
|
+
columns: [...this._primaryKeyConstraint.columns]
|
|
439
|
+
};
|
|
440
|
+
snapshot.tables[key] = {
|
|
441
|
+
schema: this.schema,
|
|
442
|
+
name: this.name,
|
|
443
|
+
columns,
|
|
444
|
+
indexes: {},
|
|
445
|
+
checkConstraints: checks,
|
|
446
|
+
uniqueConstraints,
|
|
447
|
+
primaryKeyConstraint
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
/**
|
|
452
|
+
* DDL statement that drops an existing table.
|
|
453
|
+
*
|
|
454
|
+
* Generates: `DROP TABLE "schema"."name";`
|
|
455
|
+
*
|
|
456
|
+
* @example
|
|
457
|
+
* ```typescript
|
|
458
|
+
* ddl.dropTable('public', 'users');
|
|
459
|
+
* // DROP TABLE "public"."users";
|
|
460
|
+
* ```
|
|
461
|
+
*/
|
|
462
|
+
var DropTableStatement = class extends DDLStatement {
|
|
463
|
+
type = "dropTable";
|
|
464
|
+
/**
|
|
465
|
+
* @param schema - The schema of the table.
|
|
466
|
+
* @param name - The table name to drop.
|
|
467
|
+
*/
|
|
468
|
+
constructor(schema, name) {
|
|
469
|
+
super();
|
|
470
|
+
this.schema = schema;
|
|
471
|
+
this.name = name;
|
|
472
|
+
}
|
|
473
|
+
toSQL() {
|
|
474
|
+
return `DROP TABLE ${buildRelation(this.schema, this.name)};`;
|
|
475
|
+
}
|
|
476
|
+
applyToSnapshot(snapshot) {
|
|
477
|
+
const key = `${this.schema}.${this.name}`;
|
|
478
|
+
delete snapshot.tables[key];
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
/**
|
|
482
|
+
* DDL statement that renames an existing table.
|
|
483
|
+
*
|
|
484
|
+
* Generates: `ALTER TABLE "schema"."oldName" RENAME TO "newName";`
|
|
485
|
+
*
|
|
486
|
+
* @example
|
|
487
|
+
* ```typescript
|
|
488
|
+
* ddl.renameTable('public', 'users', 'accounts');
|
|
489
|
+
* // ALTER TABLE "public"."users" RENAME TO "accounts";
|
|
490
|
+
* ```
|
|
491
|
+
*/
|
|
492
|
+
var RenameTableStatement = class extends DDLStatement {
|
|
493
|
+
type = "renameTable";
|
|
494
|
+
/**
|
|
495
|
+
* @param schema - The schema of the table.
|
|
496
|
+
* @param oldName - The current table name.
|
|
497
|
+
* @param newName - The new table name.
|
|
498
|
+
*/
|
|
499
|
+
constructor(schema, oldName, newName) {
|
|
500
|
+
super();
|
|
501
|
+
this.schema = schema;
|
|
502
|
+
this.oldName = oldName;
|
|
503
|
+
this.newName = newName;
|
|
504
|
+
}
|
|
505
|
+
toSQL() {
|
|
506
|
+
return `ALTER TABLE ${buildRelation(this.schema, this.oldName)} RENAME TO "${this.newName}";`;
|
|
507
|
+
}
|
|
508
|
+
applyToSnapshot(snapshot) {
|
|
509
|
+
const oldKey = `${this.schema}.${this.oldName}`;
|
|
510
|
+
const newKey = `${this.schema}.${this.newName}`;
|
|
511
|
+
const table = snapshot.tables[oldKey];
|
|
512
|
+
if (!table) return;
|
|
513
|
+
table.name = this.newName;
|
|
514
|
+
snapshot.tables[newKey] = table;
|
|
515
|
+
delete snapshot.tables[oldKey];
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
/**
|
|
519
|
+
* Chainable builder that constructs `ALTER TABLE` DDL statements.
|
|
520
|
+
*
|
|
521
|
+
* Supports adding/dropping columns, changing types, toggling constraints,
|
|
522
|
+
* and managing defaults. Each chained method appends an action that produces
|
|
523
|
+
* a separate `ALTER TABLE ... ;` SQL statement when {@link toSQL} is called.
|
|
524
|
+
*
|
|
525
|
+
* Use {@link ddl.alterTable} to obtain an instance.
|
|
526
|
+
*
|
|
527
|
+
* @example
|
|
528
|
+
* ```typescript
|
|
529
|
+
* ddl.alterTable('public', 'users')
|
|
530
|
+
* .addColumn('age', 'integer', { notNull: true, default: '0' })
|
|
531
|
+
* .dropColumn('legacy_field')
|
|
532
|
+
* .setNotNull('email')
|
|
533
|
+
* .addUniqueConstraint('users_email_unique', ['email']);
|
|
534
|
+
* ```
|
|
535
|
+
*/
|
|
536
|
+
var AlterTableBuilder = class extends DDLStatement {
|
|
537
|
+
type = "alterTable";
|
|
538
|
+
actions = [];
|
|
539
|
+
/**
|
|
540
|
+
* @param schema - The schema of the table to alter.
|
|
541
|
+
* @param name - The table name.
|
|
542
|
+
*/
|
|
543
|
+
constructor(schema, name) {
|
|
544
|
+
super();
|
|
545
|
+
this.schema = schema;
|
|
546
|
+
this.name = name;
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Add a new column to the table.
|
|
550
|
+
*
|
|
551
|
+
* @param name - Column name.
|
|
552
|
+
* @param type - SQL type (e.g. `"varchar(255)"`).
|
|
553
|
+
* @param options - Column constraints and options.
|
|
554
|
+
* @returns `this` for chaining.
|
|
555
|
+
*/
|
|
556
|
+
addColumn(name, type, options = {}) {
|
|
557
|
+
this.actions.push({
|
|
558
|
+
type: "addColumn",
|
|
559
|
+
name,
|
|
560
|
+
colType: type,
|
|
561
|
+
options
|
|
562
|
+
});
|
|
563
|
+
return this;
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Drop a column from the table.
|
|
567
|
+
*
|
|
568
|
+
* @param name - The column name to drop.
|
|
569
|
+
* @returns `this` for chaining.
|
|
570
|
+
*/
|
|
571
|
+
dropColumn(name) {
|
|
572
|
+
this.actions.push({
|
|
573
|
+
type: "dropColumn",
|
|
574
|
+
name
|
|
575
|
+
});
|
|
576
|
+
return this;
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Rename a column.
|
|
580
|
+
*
|
|
581
|
+
* @param oldName - The current column name.
|
|
582
|
+
* @param newName - The new column name.
|
|
583
|
+
* @returns `this` for chaining.
|
|
584
|
+
*/
|
|
585
|
+
renameColumn(oldName, newName) {
|
|
586
|
+
this.actions.push({
|
|
587
|
+
type: "renameColumn",
|
|
588
|
+
oldName,
|
|
589
|
+
newName
|
|
590
|
+
});
|
|
591
|
+
return this;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Change the type of an existing column.
|
|
595
|
+
*
|
|
596
|
+
* @param name - The column name.
|
|
597
|
+
* @param newType - The new SQL type.
|
|
598
|
+
* @returns `this` for chaining.
|
|
599
|
+
*/
|
|
600
|
+
alterColumnType(name, newType) {
|
|
601
|
+
this.actions.push({
|
|
602
|
+
type: "alterColumnType",
|
|
603
|
+
name,
|
|
604
|
+
newType
|
|
605
|
+
});
|
|
606
|
+
return this;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Add a column-level UNIQUE constraint.
|
|
610
|
+
*
|
|
611
|
+
* @param column - The column name.
|
|
612
|
+
* @returns `this` for chaining.
|
|
613
|
+
*/
|
|
614
|
+
addUnique(column) {
|
|
615
|
+
this.actions.push({
|
|
616
|
+
type: "addUnique",
|
|
617
|
+
column
|
|
618
|
+
});
|
|
619
|
+
return this;
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Drop a named constraint (UNIQUE, CHECK, or PRIMARY KEY).
|
|
623
|
+
*
|
|
624
|
+
* @param name - The constraint name.
|
|
625
|
+
* @returns `this` for chaining.
|
|
626
|
+
*/
|
|
627
|
+
dropConstraint(name) {
|
|
628
|
+
this.actions.push({
|
|
629
|
+
type: "dropConstraint",
|
|
630
|
+
name
|
|
631
|
+
});
|
|
632
|
+
return this;
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Set `NOT NULL` on a column.
|
|
636
|
+
*
|
|
637
|
+
* @param column - The column name.
|
|
638
|
+
* @returns `this` for chaining.
|
|
639
|
+
*/
|
|
640
|
+
setNotNull(column) {
|
|
641
|
+
this.actions.push({
|
|
642
|
+
type: "setNotNull",
|
|
643
|
+
column
|
|
644
|
+
});
|
|
645
|
+
return this;
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Drop `NOT NULL` from a column, making it nullable.
|
|
649
|
+
*
|
|
650
|
+
* @param column - The column name.
|
|
651
|
+
* @returns `this` for chaining.
|
|
652
|
+
*/
|
|
653
|
+
dropNotNull(column) {
|
|
654
|
+
this.actions.push({
|
|
655
|
+
type: "dropNotNull",
|
|
656
|
+
column
|
|
657
|
+
});
|
|
658
|
+
return this;
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Set or change the DEFAULT value for a column.
|
|
662
|
+
*
|
|
663
|
+
* @param column - The column name.
|
|
664
|
+
* @param defaultValue - The new default value as a raw SQL expression.
|
|
665
|
+
* @returns `this` for chaining.
|
|
666
|
+
*/
|
|
667
|
+
setDefault(column, defaultValue) {
|
|
668
|
+
this.actions.push({
|
|
669
|
+
type: "setDefault",
|
|
670
|
+
column,
|
|
671
|
+
defaultValue
|
|
672
|
+
});
|
|
673
|
+
return this;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Drop the DEFAULT value from a column.
|
|
677
|
+
*
|
|
678
|
+
* @param column - The column name.
|
|
679
|
+
* @returns `this` for chaining.
|
|
680
|
+
*/
|
|
681
|
+
dropDefault(column) {
|
|
682
|
+
this.actions.push({
|
|
683
|
+
type: "dropDefault",
|
|
684
|
+
column
|
|
685
|
+
});
|
|
686
|
+
return this;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Add a CHECK constraint to the table.
|
|
690
|
+
*
|
|
691
|
+
* @param name - Constraint name.
|
|
692
|
+
* @param expr - The check expression.
|
|
693
|
+
* @returns `this` for chaining.
|
|
694
|
+
*/
|
|
695
|
+
addCheck(name, expr) {
|
|
696
|
+
this.actions.push({
|
|
697
|
+
type: "addCheck",
|
|
698
|
+
name,
|
|
699
|
+
expr
|
|
700
|
+
});
|
|
701
|
+
return this;
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Add a table-level UNIQUE constraint spanning one or more columns.
|
|
705
|
+
*
|
|
706
|
+
* @param name - Constraint name.
|
|
707
|
+
* @param columns - Column names that form the unique key.
|
|
708
|
+
* @returns `this` for chaining.
|
|
709
|
+
*/
|
|
710
|
+
addUniqueConstraint(name, columns) {
|
|
711
|
+
this.actions.push({
|
|
712
|
+
type: "addUniqueConstraint",
|
|
713
|
+
name,
|
|
714
|
+
columns
|
|
715
|
+
});
|
|
716
|
+
return this;
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Add a composite PRIMARY KEY constraint.
|
|
720
|
+
*
|
|
721
|
+
* @param name - Constraint name.
|
|
722
|
+
* @param columns - Column names that form the primary key.
|
|
723
|
+
* @returns `this` for chaining.
|
|
724
|
+
*/
|
|
725
|
+
addPrimaryKeyConstraint(name, columns) {
|
|
726
|
+
this.actions.push({
|
|
727
|
+
type: "addPrimaryKeyConstraint",
|
|
728
|
+
name,
|
|
729
|
+
columns
|
|
730
|
+
});
|
|
731
|
+
return this;
|
|
732
|
+
}
|
|
733
|
+
toSQL() {
|
|
734
|
+
const relation = buildRelation(this.schema, this.name);
|
|
735
|
+
const statements = [];
|
|
736
|
+
for (const action of this.actions) switch (action.type) {
|
|
737
|
+
case "addColumn":
|
|
738
|
+
statements.push(`ALTER TABLE ${relation} ADD COLUMN ${toColumnDef(action.name, action.colType, action.options)};`);
|
|
739
|
+
break;
|
|
740
|
+
case "dropColumn":
|
|
741
|
+
statements.push(`ALTER TABLE ${relation} DROP COLUMN "${action.name}";`);
|
|
742
|
+
break;
|
|
743
|
+
case "renameColumn":
|
|
744
|
+
statements.push(`ALTER TABLE ${relation} RENAME COLUMN "${action.oldName}" TO "${action.newName}";`);
|
|
745
|
+
break;
|
|
746
|
+
case "alterColumnType":
|
|
747
|
+
statements.push(`ALTER TABLE ${relation} ALTER COLUMN "${action.name}" TYPE ${action.newType};`);
|
|
748
|
+
break;
|
|
749
|
+
case "addUnique":
|
|
750
|
+
statements.push(`ALTER TABLE ${relation} ADD UNIQUE (${action.column});`);
|
|
751
|
+
break;
|
|
752
|
+
case "dropConstraint":
|
|
753
|
+
statements.push(`ALTER TABLE ${relation} DROP CONSTRAINT ${action.name};`);
|
|
754
|
+
break;
|
|
755
|
+
case "setNotNull":
|
|
756
|
+
statements.push(`ALTER TABLE ${relation} ALTER COLUMN "${action.column}" SET NOT NULL;`);
|
|
757
|
+
break;
|
|
758
|
+
case "dropNotNull":
|
|
759
|
+
statements.push(`ALTER TABLE ${relation} ALTER COLUMN "${action.column}" DROP NOT NULL;`);
|
|
760
|
+
break;
|
|
761
|
+
case "setDefault":
|
|
762
|
+
statements.push(`ALTER TABLE ${relation} ALTER COLUMN "${action.column}" SET DEFAULT '${action.defaultValue}';`);
|
|
763
|
+
break;
|
|
764
|
+
case "dropDefault":
|
|
765
|
+
statements.push(`ALTER TABLE ${relation} ALTER COLUMN "${action.column}" DROP DEFAULT;`);
|
|
766
|
+
break;
|
|
767
|
+
case "addCheck":
|
|
768
|
+
statements.push(`ALTER TABLE ${relation} ADD CONSTRAINT ${action.name} CHECK (${snapshotExprToSQL(action.expr)});`);
|
|
769
|
+
break;
|
|
770
|
+
case "addUniqueConstraint": {
|
|
771
|
+
const cols = action.columns.map((c) => `"${c}"`).join(", ");
|
|
772
|
+
statements.push(`ALTER TABLE ${relation} ADD CONSTRAINT ${action.name} UNIQUE (${cols});`);
|
|
773
|
+
break;
|
|
774
|
+
}
|
|
775
|
+
case "addPrimaryKeyConstraint": {
|
|
776
|
+
const cols = action.columns.map((c) => `"${c}"`).join(", ");
|
|
777
|
+
statements.push(`ALTER TABLE ${relation} ADD CONSTRAINT ${action.name} PRIMARY KEY (${cols});`);
|
|
778
|
+
break;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
return statements.join("\n");
|
|
782
|
+
}
|
|
783
|
+
applyToSnapshot(snapshot) {
|
|
784
|
+
const key = `${this.schema}.${this.name}`;
|
|
785
|
+
const table = snapshot.tables[key];
|
|
786
|
+
if (!table) return;
|
|
787
|
+
for (const action of this.actions) switch (action.type) {
|
|
788
|
+
case "addColumn": {
|
|
789
|
+
const colSnapshot = { type: action.colType };
|
|
790
|
+
if (action.options.notNull) colSnapshot.notNull = true;
|
|
791
|
+
if (action.options.primaryKey) colSnapshot.primaryKey = true;
|
|
792
|
+
if (action.options.unique) colSnapshot.unique = true;
|
|
793
|
+
if (action.options.default !== void 0) colSnapshot.default = action.options.default;
|
|
794
|
+
if (action.options.generated) colSnapshot.generated = action.options.generated;
|
|
795
|
+
if (action.options.as) colSnapshot.as = action.options.as;
|
|
796
|
+
if (action.options.references) colSnapshot.references = {
|
|
797
|
+
schema: action.options.references.schema,
|
|
798
|
+
table: action.options.references.table,
|
|
799
|
+
column: action.options.references.column,
|
|
800
|
+
onDelete: action.options.references.onDelete
|
|
801
|
+
};
|
|
802
|
+
table.columns[action.name] = colSnapshot;
|
|
803
|
+
break;
|
|
804
|
+
}
|
|
805
|
+
case "dropColumn":
|
|
806
|
+
delete table.columns[action.name];
|
|
807
|
+
break;
|
|
808
|
+
case "renameColumn": {
|
|
809
|
+
const col = table.columns[action.oldName];
|
|
810
|
+
if (col) {
|
|
811
|
+
table.columns[action.newName] = col;
|
|
812
|
+
delete table.columns[action.oldName];
|
|
813
|
+
}
|
|
814
|
+
break;
|
|
815
|
+
}
|
|
816
|
+
case "alterColumnType":
|
|
817
|
+
if (table.columns[action.name]) table.columns[action.name].type = action.newType;
|
|
818
|
+
break;
|
|
819
|
+
case "addUnique":
|
|
820
|
+
if (table.columns[action.column]) table.columns[action.column].unique = true;
|
|
821
|
+
break;
|
|
822
|
+
case "dropConstraint":
|
|
823
|
+
if (action.name.endsWith("_key")) {
|
|
824
|
+
const colName = action.name.replace(`${this.name}_`, "").replace("_key", "");
|
|
825
|
+
if (table.columns[colName]) delete table.columns[colName].unique;
|
|
826
|
+
}
|
|
827
|
+
delete table.checkConstraints[action.name];
|
|
828
|
+
if (table.uniqueConstraints) delete table.uniqueConstraints[action.name];
|
|
829
|
+
if (table.primaryKeyConstraint && table.primaryKeyConstraint.name === action.name) delete table.primaryKeyConstraint;
|
|
830
|
+
break;
|
|
831
|
+
case "setNotNull":
|
|
832
|
+
if (table.columns[action.column]) table.columns[action.column].notNull = true;
|
|
833
|
+
break;
|
|
834
|
+
case "dropNotNull":
|
|
835
|
+
if (table.columns[action.column]) delete table.columns[action.column].notNull;
|
|
836
|
+
break;
|
|
837
|
+
case "setDefault":
|
|
838
|
+
if (table.columns[action.column]) table.columns[action.column].default = action.defaultValue;
|
|
839
|
+
break;
|
|
840
|
+
case "dropDefault":
|
|
841
|
+
if (table.columns[action.column]) delete table.columns[action.column].default;
|
|
842
|
+
break;
|
|
843
|
+
case "addCheck": {
|
|
844
|
+
const tableKey = `${this.schema}.${this.name}`;
|
|
845
|
+
table.checkConstraints[action.name] = {
|
|
846
|
+
name: action.name,
|
|
847
|
+
table: tableKey,
|
|
848
|
+
expr: action.expr
|
|
849
|
+
};
|
|
850
|
+
break;
|
|
851
|
+
}
|
|
852
|
+
case "addUniqueConstraint": {
|
|
853
|
+
const tableKey = `${this.schema}.${this.name}`;
|
|
854
|
+
if (!table.uniqueConstraints) table.uniqueConstraints = {};
|
|
855
|
+
table.uniqueConstraints[action.name] = {
|
|
856
|
+
name: action.name,
|
|
857
|
+
table: tableKey,
|
|
858
|
+
columns: [...action.columns]
|
|
859
|
+
};
|
|
860
|
+
break;
|
|
861
|
+
}
|
|
862
|
+
case "addPrimaryKeyConstraint": {
|
|
863
|
+
const tableKey = `${this.schema}.${this.name}`;
|
|
864
|
+
table.primaryKeyConstraint = {
|
|
865
|
+
name: action.name,
|
|
866
|
+
table: tableKey,
|
|
867
|
+
columns: [...action.columns]
|
|
868
|
+
};
|
|
869
|
+
break;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
/**
|
|
875
|
+
* Chainable builder that constructs a `CREATE INDEX` DDL statement.
|
|
876
|
+
*
|
|
877
|
+
* Use {@link ddl.createIndex} to obtain an instance, then chain `.on()`,
|
|
878
|
+
* and optionally `.using()` and `.unique()`.
|
|
879
|
+
*
|
|
880
|
+
* @example
|
|
881
|
+
* ```typescript
|
|
882
|
+
* ddl.createIndex('idx_users_email')
|
|
883
|
+
* .on('public', 'users', ['email'])
|
|
884
|
+
* .using('btree')
|
|
885
|
+
* .unique();
|
|
886
|
+
* // CREATE UNIQUE INDEX idx_users_email ON "public"."users" USING btree ("email");
|
|
887
|
+
* ```
|
|
888
|
+
*/
|
|
889
|
+
var CreateIndexBuilder = class extends DDLStatement {
|
|
890
|
+
type = "createIndex";
|
|
891
|
+
tableSchema = "";
|
|
892
|
+
tableName = "";
|
|
893
|
+
indexType = "btree";
|
|
894
|
+
indexColumns = [];
|
|
895
|
+
isUnique = false;
|
|
896
|
+
isConcurrent = false;
|
|
897
|
+
/**
|
|
898
|
+
* @param indexName - The name of the index to create.
|
|
899
|
+
*/
|
|
900
|
+
constructor(indexName) {
|
|
901
|
+
super();
|
|
902
|
+
this.indexName = indexName;
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* Build the index concurrently, without locking writes on the table.
|
|
906
|
+
*
|
|
907
|
+
* Generates: `CREATE INDEX CONCURRENTLY ...`
|
|
908
|
+
*
|
|
909
|
+
* @remarks
|
|
910
|
+
* Concurrent index creation cannot run inside a transaction.
|
|
911
|
+
* Set `transaction: false` in your migration options when using this.
|
|
912
|
+
*
|
|
913
|
+
* @returns `this` for chaining.
|
|
914
|
+
*/
|
|
915
|
+
concurrently() {
|
|
916
|
+
this.isConcurrent = true;
|
|
917
|
+
return this;
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Specify the table and columns this index is created on.
|
|
921
|
+
*
|
|
922
|
+
* @param schema - The table's schema.
|
|
923
|
+
* @param table - The table name.
|
|
924
|
+
* @param columns - Optional array of column names to index.
|
|
925
|
+
* @returns `this` for chaining.
|
|
926
|
+
*/
|
|
927
|
+
on(schema, table, columns) {
|
|
928
|
+
this.tableSchema = schema;
|
|
929
|
+
this.tableName = table;
|
|
930
|
+
if (columns) this.indexColumns = columns;
|
|
931
|
+
return this;
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Specify the index method.
|
|
935
|
+
*
|
|
936
|
+
* @param type - The index type (`"btree"`, `"hash"`, `"gin"`, `"gist"`, etc.).
|
|
937
|
+
* @param columns - Optional array of column names to index.
|
|
938
|
+
* @returns `this` for chaining.
|
|
939
|
+
*/
|
|
940
|
+
using(type, columns) {
|
|
941
|
+
this.indexType = type;
|
|
942
|
+
if (columns) this.indexColumns = columns;
|
|
943
|
+
return this;
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* Make this a unique index.
|
|
947
|
+
*
|
|
948
|
+
* @returns `this` for chaining.
|
|
949
|
+
*/
|
|
950
|
+
unique() {
|
|
951
|
+
this.isUnique = true;
|
|
952
|
+
return this;
|
|
953
|
+
}
|
|
954
|
+
toSQL() {
|
|
955
|
+
const tableRelation = buildRelation(this.tableSchema, this.tableName);
|
|
956
|
+
const columns = this.indexColumns.map((c) => `"${c}"`).join(", ");
|
|
957
|
+
return `CREATE${this.isUnique ? " UNIQUE" : ""} INDEX${this.isConcurrent ? " CONCURRENTLY" : ""} ${this.indexName} ON ${tableRelation} USING ${this.indexType} (${columns});`;
|
|
958
|
+
}
|
|
959
|
+
applyToSnapshot(snapshot) {
|
|
960
|
+
const tableKey = `${this.tableSchema}.${this.tableName}`;
|
|
961
|
+
const table = snapshot.tables[tableKey];
|
|
962
|
+
if (!table) return;
|
|
963
|
+
table.indexes[this.indexName] = {
|
|
964
|
+
name: this.indexName,
|
|
965
|
+
table: tableKey,
|
|
966
|
+
columns: [...this.indexColumns],
|
|
967
|
+
type: this.indexType,
|
|
968
|
+
unique: this.isUnique
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
/**
|
|
973
|
+
* DDL statement builder that drops an existing index.
|
|
974
|
+
*
|
|
975
|
+
* Generates: `DROP INDEX [CONCURRENTLY] <name>;`
|
|
976
|
+
*
|
|
977
|
+
* @example
|
|
978
|
+
* ```typescript
|
|
979
|
+
* ddl.dropIndex('idx_users_email');
|
|
980
|
+
* // DROP INDEX idx_users_email;
|
|
981
|
+
*
|
|
982
|
+
* ddl.dropIndex('idx_users_email').concurrently();
|
|
983
|
+
* // DROP INDEX CONCURRENTLY idx_users_email;
|
|
984
|
+
* ```
|
|
985
|
+
*/
|
|
986
|
+
var DropIndexStatement = class extends DDLStatement {
|
|
987
|
+
type = "dropIndex";
|
|
988
|
+
isConcurrent = false;
|
|
989
|
+
/**
|
|
990
|
+
* @param indexName - The name of the index to drop.
|
|
991
|
+
*/
|
|
992
|
+
constructor(indexName) {
|
|
993
|
+
super();
|
|
994
|
+
this.indexName = indexName;
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Drop the index concurrently, without locking writes on the table.
|
|
998
|
+
*
|
|
999
|
+
* Generates: `DROP INDEX CONCURRENTLY ...`
|
|
1000
|
+
*
|
|
1001
|
+
* @remarks
|
|
1002
|
+
* Concurrent index drops cannot run inside a transaction.
|
|
1003
|
+
* Set `transaction: false` in your migration options when using this.
|
|
1004
|
+
*
|
|
1005
|
+
* @returns `this` for chaining.
|
|
1006
|
+
*/
|
|
1007
|
+
concurrently() {
|
|
1008
|
+
this.isConcurrent = true;
|
|
1009
|
+
return this;
|
|
1010
|
+
}
|
|
1011
|
+
toSQL() {
|
|
1012
|
+
return `DROP INDEX${this.isConcurrent ? " CONCURRENTLY" : ""} ${this.indexName};`;
|
|
1013
|
+
}
|
|
1014
|
+
applyToSnapshot(snapshot) {
|
|
1015
|
+
for (const table of Object.values(snapshot.tables)) if (table.indexes[this.indexName]) {
|
|
1016
|
+
delete table.indexes[this.indexName];
|
|
1017
|
+
break;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
};
|
|
1021
|
+
/**
|
|
1022
|
+
* The main DDL builder entry point.
|
|
1023
|
+
*
|
|
1024
|
+
* Provides factory methods for all supported DDL operations.
|
|
1025
|
+
* Import from `durcno/migration` and use in migration files.
|
|
1026
|
+
*
|
|
1027
|
+
* @example
|
|
1028
|
+
* ```typescript
|
|
1029
|
+
* import { ddl, type DDLStatement } from 'durcno/migration';
|
|
1030
|
+
*
|
|
1031
|
+
* export const statements: DDLStatement[] = [
|
|
1032
|
+
* ddl.createEnum('public', 'user_type', ['admin', 'user']),
|
|
1033
|
+
* ddl.createTable('public', 'users')
|
|
1034
|
+
* .column('id', 'serial', { primaryKey: true })
|
|
1035
|
+
* .column('name', 'varchar(255)', { notNull: true }),
|
|
1036
|
+
* ];
|
|
1037
|
+
* ```
|
|
1038
|
+
*/
|
|
1039
|
+
const ddl = {
|
|
1040
|
+
createSchema(name) {
|
|
1041
|
+
return new CreateSchemaStatement(name);
|
|
1042
|
+
},
|
|
1043
|
+
dropSchema(name) {
|
|
1044
|
+
return new DropSchemaStatement(name);
|
|
1045
|
+
},
|
|
1046
|
+
createEnum(schema, name, values) {
|
|
1047
|
+
return new CreateEnumStatement(schema, name, values);
|
|
1048
|
+
},
|
|
1049
|
+
alterEnumAddValue(schema, name, value, position) {
|
|
1050
|
+
return new AlterEnumAddValueStatement(schema, name, value, position);
|
|
1051
|
+
},
|
|
1052
|
+
dropEnum(schema, name) {
|
|
1053
|
+
return new DropEnumStatement(schema, name);
|
|
1054
|
+
},
|
|
1055
|
+
createSequence(schema, name, options) {
|
|
1056
|
+
return new CreateSequenceStatement(schema, name, options);
|
|
1057
|
+
},
|
|
1058
|
+
dropSequence(schema, name) {
|
|
1059
|
+
return new DropSequenceStatement(schema, name);
|
|
1060
|
+
},
|
|
1061
|
+
createTable(schema, name) {
|
|
1062
|
+
return new CreateTableBuilder(schema, name);
|
|
1063
|
+
},
|
|
1064
|
+
dropTable(schema, name) {
|
|
1065
|
+
return new DropTableStatement(schema, name);
|
|
1066
|
+
},
|
|
1067
|
+
renameTable(schema, oldName, newName) {
|
|
1068
|
+
return new RenameTableStatement(schema, oldName, newName);
|
|
1069
|
+
},
|
|
1070
|
+
alterTable(schema, name) {
|
|
1071
|
+
return new AlterTableBuilder(schema, name);
|
|
1072
|
+
},
|
|
1073
|
+
createIndex(name) {
|
|
1074
|
+
return new CreateIndexBuilder(name);
|
|
1075
|
+
},
|
|
1076
|
+
dropIndex(name) {
|
|
1077
|
+
return new DropIndexStatement(name);
|
|
1078
|
+
},
|
|
1079
|
+
custom(sql) {
|
|
1080
|
+
return new CustomStatement(sql);
|
|
1081
|
+
}
|
|
1082
|
+
};
|
|
1083
|
+
//#endregion
|
|
1084
|
+
export { ddl };
|