sedentary-pg 0.0.14 → 0.0.18
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/README.md +46 -1
- package/index.d.ts +5 -5
- package/index.js +11 -1
- package/lib/adsrc.d.ts +1 -0
- package/lib/adsrc.js +7 -0
- package/lib/adsrc.ts +3 -0
- package/lib/pgdb.d.ts +1 -1
- package/lib/pgdb.js +75 -48
- package/lib/pgdb.ts +61 -51
- package/package.json +11 -8
package/README.md
CHANGED
|
@@ -29,4 +29,49 @@
|
|
|
29
29
|
|
|
30
30
|
# under development
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
# Description
|
|
33
|
+
|
|
34
|
+
The **PostgreSQL** specilized package of [Sedentary](https://www.npmjs.com/package/sedentary).
|
|
35
|
+
|
|
36
|
+
# Installation
|
|
37
|
+
|
|
38
|
+
With [npm](https://www.npmjs.com/package/sedentary-pg):
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
$ npm install --save sedentary-pg
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
# Documentation
|
|
45
|
+
|
|
46
|
+
The full documentation is on [sedentary.readthedocs.io](https://sedentary.readthedocs.io/).
|
|
47
|
+
|
|
48
|
+
# Compatibility
|
|
49
|
+
|
|
50
|
+
Requires:
|
|
51
|
+
|
|
52
|
+
- Node.js: **v12**
|
|
53
|
+
- TypeScript: **v4.1** (or none if used in a JavaScript project).
|
|
54
|
+
|
|
55
|
+
The package is tested under [all version combinations](https://app.travis-ci.com/github/iccicci/sedentary-pg)
|
|
56
|
+
of **Node.js** currently supported accordingly to [Node.js Release](https://github.com/nodejs/Release#readme) and of
|
|
57
|
+
**PostgreSQL** currently supported accordingly to
|
|
58
|
+
[PostgreSQL Versioning](https://www.postgresql.org/support/versioning/).
|
|
59
|
+
|
|
60
|
+
To work with the package under Windows, be sure to configure `bash.exe` as your _script-shell_.
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
> npm config set script-shell bash.exe
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
# Licence
|
|
67
|
+
|
|
68
|
+
[MIT Licence](https://github.com/iccicci/sedentary-pg/blob/master/LICENSE)
|
|
69
|
+
|
|
70
|
+
# Bugs
|
|
71
|
+
|
|
72
|
+
Do not hesitate to report any bug or inconsistency [@github](https://github.com/iccicci/sedentary-pg/issues).
|
|
73
|
+
|
|
74
|
+
# Donating
|
|
75
|
+
|
|
76
|
+
If you find useful this package, please consider the opportunity to donate some satoshis to this bitcoin address:
|
|
77
|
+
**1Md9WFAHrXTb3yPBwQWmUfv2RmzrtbHioB**
|
package/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Entry, ForeignKeyOptions, Natural, SedentaryOptions, Sedentary, Type } from "sedentary";
|
|
2
2
|
import { PoolConfig } from "pg";
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
}
|
|
3
|
+
export { AttributeDefinition, AttributeOptions, AttributesDefinition, Entry, ForeignKeyActions, ForeignKeyOptions } from "sedentary";
|
|
4
|
+
export { IndexAttributes, IndexDefinition, IndexOptions, IndexesDefinition, ModelOptions, Natural, SedentaryOptions, Type, TypeDefinition } from "sedentary";
|
|
6
5
|
export declare class SedentaryPG extends Sedentary {
|
|
7
|
-
constructor(connection: PoolConfig, options?:
|
|
6
|
+
constructor(connection: PoolConfig, options?: SedentaryOptions);
|
|
7
|
+
FKEY<N extends Natural, E extends Entry>(attribute: Type<N, E>, options?: ForeignKeyOptions): Type<N, E>;
|
|
8
8
|
}
|
|
9
9
|
export declare const Package: typeof SedentaryPG;
|
package/index.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Package = exports.SedentaryPG = void 0;
|
|
3
|
+
exports.Package = exports.SedentaryPG = exports.Type = exports.Entry = void 0;
|
|
4
4
|
const sedentary_1 = require("sedentary");
|
|
5
5
|
const pgdb_1 = require("./lib/pgdb");
|
|
6
|
+
var sedentary_2 = require("sedentary");
|
|
7
|
+
Object.defineProperty(exports, "Entry", { enumerable: true, get: function () { return sedentary_2.Entry; } });
|
|
8
|
+
var sedentary_3 = require("sedentary");
|
|
9
|
+
Object.defineProperty(exports, "Type", { enumerable: true, get: function () { return sedentary_3.Type; } });
|
|
6
10
|
class SedentaryPG extends sedentary_1.Sedentary {
|
|
7
11
|
constructor(connection, options) {
|
|
8
12
|
super("", options);
|
|
@@ -10,6 +14,12 @@ class SedentaryPG extends sedentary_1.Sedentary {
|
|
|
10
14
|
throw new Error("SedentaryPG.constructor: 'connection' argument: Wrong type, expected 'Object'");
|
|
11
15
|
this.db = new pgdb_1.PGDB(connection, this.log);
|
|
12
16
|
}
|
|
17
|
+
FKEY(attribute, options) {
|
|
18
|
+
const { attributeName, modelName, unique } = attribute;
|
|
19
|
+
if (!unique)
|
|
20
|
+
throw new Error(`Sedentary.FKEY: '${modelName}' model: '${attributeName}' attribute: is not unique: can't be used as FKEY target`);
|
|
21
|
+
return super.FKEY(attribute, options);
|
|
22
|
+
}
|
|
13
23
|
}
|
|
14
24
|
exports.SedentaryPG = SedentaryPG;
|
|
15
25
|
exports.Package = SedentaryPG;
|
package/lib/adsrc.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function adsrc(version: number): "pg_get_expr(pg_attrdef.adbin, pg_attrdef.adrelid) AS adsrc" | "adsrc";
|
package/lib/adsrc.js
ADDED
package/lib/adsrc.ts
ADDED
package/lib/pgdb.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export declare class PGDB extends DB {
|
|
|
13
13
|
dropIndexes(table: Table, constraintIndexes: number[]): Promise<void>;
|
|
14
14
|
end(): Promise<void>;
|
|
15
15
|
fieldType(attribute: Attribute<Natural, unknown>): string[];
|
|
16
|
-
|
|
16
|
+
syncDataBase(): Promise<void>;
|
|
17
17
|
syncConstraints(table: Table): Promise<void>;
|
|
18
18
|
syncFields(table: Table): Promise<void>;
|
|
19
19
|
syncIndexes(table: Table): Promise<void>;
|
package/lib/pgdb.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.PGDB = void 0;
|
|
|
7
7
|
const pg_1 = require("pg");
|
|
8
8
|
const pg_format_1 = __importDefault(require("pg-format"));
|
|
9
9
|
const db_1 = require("sedentary/lib/db");
|
|
10
|
+
const adsrc_1 = require("./adsrc");
|
|
10
11
|
const needDrop = [
|
|
11
12
|
["DATETIME", "int2"],
|
|
12
13
|
["DATETIME", "int4"],
|
|
@@ -20,6 +21,7 @@ const needUsing = [
|
|
|
20
21
|
["INT8", "varchar"]
|
|
21
22
|
];
|
|
22
23
|
const types = { int2: "SMALLINT", int4: "INTEGER", int8: "BIGINT", varchar: "VARCHAR" };
|
|
24
|
+
const actions = { cascade: "c", "no action": "a", restrict: "r", "set default": "d", "set null": "n" };
|
|
23
25
|
class PGDB extends db_1.DB {
|
|
24
26
|
constructor(connection, log) {
|
|
25
27
|
super(log);
|
|
@@ -32,28 +34,38 @@ class PGDB extends db_1.DB {
|
|
|
32
34
|
}
|
|
33
35
|
async dropConstraints(table) {
|
|
34
36
|
const indexes = [];
|
|
35
|
-
const res = await this.client.query("SELECT
|
|
37
|
+
const res = await this.client.query("SELECT confdeltype, confupdtype, conindid, conname, contype FROM pg_constraint WHERE conrelid = $1 ORDER BY conname", [table.oid]);
|
|
36
38
|
for (const row of res.rows) {
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
+
const arr = table.constraints.filter(_ => _.constraintName === row.conname && _.type === row.contype);
|
|
40
|
+
let drop = false;
|
|
41
|
+
if (arr.length === 0)
|
|
42
|
+
drop = true;
|
|
43
|
+
else if (row.contype === "u")
|
|
44
|
+
indexes.push(row.conindid);
|
|
45
|
+
else {
|
|
46
|
+
const { options } = arr[0].attribute.foreignKey;
|
|
47
|
+
if (actions[options.onDelete] !== row.confdeltype || actions[options.onUpdate] !== row.confupdtype)
|
|
48
|
+
drop = true;
|
|
49
|
+
}
|
|
50
|
+
if (drop) {
|
|
39
51
|
const statement = `ALTER TABLE ${table.tableName} DROP CONSTRAINT ${row.conname} CASCADE`;
|
|
40
|
-
this.
|
|
41
|
-
|
|
52
|
+
this.syncLog(statement);
|
|
53
|
+
if (this.sync)
|
|
54
|
+
await this.client.query(statement);
|
|
42
55
|
}
|
|
43
|
-
else
|
|
44
|
-
indexes.push(row.conindid);
|
|
45
56
|
}
|
|
46
57
|
return indexes;
|
|
47
58
|
}
|
|
48
59
|
async dropField(tableName, fieldName) {
|
|
49
60
|
const statement = `ALTER TABLE ${tableName} DROP COLUMN ${fieldName}`;
|
|
50
|
-
this.
|
|
51
|
-
|
|
61
|
+
this.syncLog(statement);
|
|
62
|
+
if (this.sync)
|
|
63
|
+
await this.client.query(statement);
|
|
52
64
|
}
|
|
53
65
|
async dropFields(table) {
|
|
54
66
|
const res = await this.client.query("SELECT attname FROM pg_attribute WHERE attrelid = $1 AND attnum > 0 AND attisdropped = false AND attinhcount = 0", [table.oid]);
|
|
55
67
|
for (const i in res.rows)
|
|
56
|
-
if (table.
|
|
68
|
+
if (!table.findField(res.rows[i].attname))
|
|
57
69
|
await this.dropField(table.tableName, res.rows[i].attname);
|
|
58
70
|
}
|
|
59
71
|
async dropIndexes(table, constraintIndexes) {
|
|
@@ -79,8 +91,9 @@ class PGDB extends db_1.DB {
|
|
|
79
91
|
}
|
|
80
92
|
for (const index of Object.keys(iobject).sort()) {
|
|
81
93
|
const statement = `DROP INDEX ${index}`;
|
|
82
|
-
this.
|
|
83
|
-
|
|
94
|
+
this.syncLog(statement);
|
|
95
|
+
if (this.sync)
|
|
96
|
+
await this.client.query(statement);
|
|
84
97
|
}
|
|
85
98
|
}
|
|
86
99
|
async end() {
|
|
@@ -102,10 +115,10 @@ class PGDB extends db_1.DB {
|
|
|
102
115
|
}
|
|
103
116
|
throw new Error(`Unknown type: '${type}', '${size}'`);
|
|
104
117
|
}
|
|
105
|
-
async
|
|
118
|
+
async syncDataBase() {
|
|
106
119
|
let err;
|
|
107
120
|
try {
|
|
108
|
-
await super.
|
|
121
|
+
await super.syncDataBase();
|
|
109
122
|
}
|
|
110
123
|
catch (e) {
|
|
111
124
|
err = e;
|
|
@@ -123,17 +136,18 @@ class PGDB extends db_1.DB {
|
|
|
123
136
|
]);
|
|
124
137
|
if (!res.rowCount) {
|
|
125
138
|
let query;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
query = `UNIQUE(${attribute.fieldName})`;
|
|
132
|
-
break;
|
|
139
|
+
if (type === "f") {
|
|
140
|
+
const { fieldName, options, tableName } = attribute.foreignKey;
|
|
141
|
+
const onDelete = options.onDelete !== "no action" ? ` ON DELETE ${options.onDelete.toUpperCase()}` : "";
|
|
142
|
+
const onUpdate = options.onUpdate !== "no action" ? ` ON UPDATE ${options.onUpdate.toUpperCase()}` : "";
|
|
143
|
+
query = `FOREIGN KEY (${attribute.fieldName}) REFERENCES ${tableName}(${fieldName})${onDelete}${onUpdate}`;
|
|
133
144
|
}
|
|
145
|
+
else
|
|
146
|
+
query = `UNIQUE(${attribute.fieldName})`;
|
|
134
147
|
const statement = `ALTER TABLE ${table.tableName} ADD CONSTRAINT ${constraintName} ${query}`;
|
|
135
|
-
this.
|
|
136
|
-
|
|
148
|
+
this.syncLog(statement);
|
|
149
|
+
if (this.sync)
|
|
150
|
+
await this.client.query(statement);
|
|
137
151
|
}
|
|
138
152
|
}
|
|
139
153
|
}
|
|
@@ -143,33 +157,39 @@ class PGDB extends db_1.DB {
|
|
|
143
157
|
const { fieldName, notNull, size } = attribute;
|
|
144
158
|
const defaultValue = attribute.defaultValue === undefined ? undefined : (0, pg_format_1.default)("%L", attribute.defaultValue);
|
|
145
159
|
const [base, type] = this.fieldType(attribute);
|
|
146
|
-
const
|
|
160
|
+
const where = "attrelid = $1 AND attnum > 0 AND atttypid = pg_type.oid AND attislocal = 't' AND attname = $2";
|
|
161
|
+
const res = await this.client.query(`SELECT attnotnull, atttypmod, typname, ${(0, adsrc_1.adsrc)(this.version)} FROM pg_type, pg_attribute LEFT JOIN pg_attrdef ON adrelid = attrelid AND adnum = attnum WHERE ${where}`, [oid, fieldName]);
|
|
147
162
|
const addField = async () => {
|
|
148
163
|
const statement = `ALTER TABLE ${tableName} ADD COLUMN ${fieldName} ${type}`;
|
|
149
|
-
this.
|
|
150
|
-
|
|
164
|
+
this.syncLog(statement);
|
|
165
|
+
if (this.sync)
|
|
166
|
+
await this.client.query(statement);
|
|
151
167
|
};
|
|
152
168
|
const dropDefault = async () => {
|
|
153
169
|
const statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} DROP DEFAULT`;
|
|
154
|
-
this.
|
|
155
|
-
|
|
170
|
+
this.syncLog(statement);
|
|
171
|
+
if (this.sync)
|
|
172
|
+
await this.client.query(statement);
|
|
156
173
|
};
|
|
157
174
|
const setNotNull = async (isNull) => {
|
|
158
175
|
if (isNull === notNull)
|
|
159
176
|
return;
|
|
160
177
|
const statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} ${notNull ? "SET" : "DROP"} NOT NULL`;
|
|
161
|
-
this.
|
|
162
|
-
|
|
178
|
+
this.syncLog(statement);
|
|
179
|
+
if (this.sync)
|
|
180
|
+
await this.client.query(statement);
|
|
163
181
|
};
|
|
164
182
|
const setDefault = async (isNull) => {
|
|
165
183
|
if (defaultValue !== undefined) {
|
|
166
184
|
let statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} SET DEFAULT ${defaultValue}`;
|
|
167
|
-
this.
|
|
168
|
-
|
|
185
|
+
this.syncLog(statement);
|
|
186
|
+
if (this.sync)
|
|
187
|
+
await this.client.query(statement);
|
|
169
188
|
if (isNull) {
|
|
170
189
|
statement = `UPDATE ${tableName} SET ${fieldName} = ${defaultValue} WHERE ${fieldName} IS NULL`;
|
|
171
|
-
this.
|
|
172
|
-
this.
|
|
190
|
+
this.syncLog(statement);
|
|
191
|
+
if (this.sync)
|
|
192
|
+
this.client.query(statement);
|
|
173
193
|
}
|
|
174
194
|
}
|
|
175
195
|
await setNotNull(isNull);
|
|
@@ -191,8 +211,9 @@ class PGDB extends db_1.DB {
|
|
|
191
211
|
dropDefault();
|
|
192
212
|
const using = needUsing.filter(([type, name]) => attribute.type === type && typname === name).length ? " USING " + fieldName + "::" + type : "";
|
|
193
213
|
const statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} TYPE ${type}${using}`;
|
|
194
|
-
this.
|
|
195
|
-
|
|
214
|
+
this.syncLog(statement);
|
|
215
|
+
if (this.sync)
|
|
216
|
+
await this.client.query(statement);
|
|
196
217
|
await setDefault(attnotnull);
|
|
197
218
|
}
|
|
198
219
|
}
|
|
@@ -212,8 +233,9 @@ class PGDB extends db_1.DB {
|
|
|
212
233
|
const { fields, indexName, type, unique } = index;
|
|
213
234
|
if (!this.indexes.includes(indexName)) {
|
|
214
235
|
const statement = `CREATE${unique ? " UNIQUE" : ""} INDEX ${indexName} ON ${tableName} USING ${type} (${fields.join(", ")})`;
|
|
215
|
-
this.
|
|
216
|
-
|
|
236
|
+
this.syncLog(statement);
|
|
237
|
+
if (this.sync)
|
|
238
|
+
await this.client.query(statement);
|
|
217
239
|
}
|
|
218
240
|
}
|
|
219
241
|
}
|
|
@@ -221,10 +243,12 @@ class PGDB extends db_1.DB {
|
|
|
221
243
|
if (!table.autoIncrementOwn)
|
|
222
244
|
return;
|
|
223
245
|
const statement = `ALTER SEQUENCE ${table.tableName}_id_seq OWNED BY ${table.tableName}.id`;
|
|
224
|
-
this.
|
|
225
|
-
|
|
246
|
+
this.syncLog(statement);
|
|
247
|
+
if (this.sync)
|
|
248
|
+
await this.client.query(statement);
|
|
226
249
|
}
|
|
227
250
|
async syncTable(table) {
|
|
251
|
+
var _a;
|
|
228
252
|
if (table.autoIncrement) {
|
|
229
253
|
await (async () => {
|
|
230
254
|
try {
|
|
@@ -235,8 +259,9 @@ class PGDB extends db_1.DB {
|
|
|
235
259
|
return;
|
|
236
260
|
if (e.code === "42P01") {
|
|
237
261
|
const statement = `CREATE SEQUENCE ${table.tableName}_id_seq`;
|
|
238
|
-
this.
|
|
239
|
-
|
|
262
|
+
this.syncLog(statement);
|
|
263
|
+
if (this.sync)
|
|
264
|
+
await this.client.query(statement);
|
|
240
265
|
table.autoIncrementOwn = true;
|
|
241
266
|
return;
|
|
242
267
|
}
|
|
@@ -253,7 +278,7 @@ class PGDB extends db_1.DB {
|
|
|
253
278
|
if (resParent.rowCount) {
|
|
254
279
|
if (!table.parent)
|
|
255
280
|
drop = true;
|
|
256
|
-
else if (this.
|
|
281
|
+
else if (this.findTable(table.parent.tableName).oid === resParent.rows[0].inhparent)
|
|
257
282
|
return;
|
|
258
283
|
drop = true;
|
|
259
284
|
}
|
|
@@ -262,8 +287,9 @@ class PGDB extends db_1.DB {
|
|
|
262
287
|
if (drop) {
|
|
263
288
|
const statement = `DROP TABLE ${table.tableName} CASCADE`;
|
|
264
289
|
create = true;
|
|
265
|
-
this.
|
|
266
|
-
|
|
290
|
+
this.syncLog(statement);
|
|
291
|
+
if (this.sync)
|
|
292
|
+
await this.client.query(statement);
|
|
267
293
|
}
|
|
268
294
|
}
|
|
269
295
|
else
|
|
@@ -271,10 +297,11 @@ class PGDB extends db_1.DB {
|
|
|
271
297
|
if (create) {
|
|
272
298
|
const parent = table.parent ? ` INHERITS (${table.parent.tableName})` : "";
|
|
273
299
|
const statement = `CREATE TABLE ${table.tableName} ()${parent}`;
|
|
274
|
-
this.
|
|
275
|
-
|
|
300
|
+
this.syncLog(statement);
|
|
301
|
+
if (this.sync)
|
|
302
|
+
await this.client.query(statement);
|
|
276
303
|
const resTable = await this.client.query("SELECT oid FROM pg_class WHERE relname = $1", [table.tableName]);
|
|
277
|
-
table.oid = resTable.rows[0].oid;
|
|
304
|
+
table.oid = (_a = resTable.rows[0]) === null || _a === void 0 ? void 0 : _a.oid;
|
|
278
305
|
}
|
|
279
306
|
}
|
|
280
307
|
}
|
package/lib/pgdb.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Pool, PoolClient, PoolConfig } from "pg";
|
|
2
2
|
import format from "pg-format";
|
|
3
|
-
import { Attribute, DB, Index, Natural, Table } from "sedentary/lib/db";
|
|
3
|
+
import { Attribute, DB, Index, Natural, ForeignKeyActions, Table } from "sedentary/lib/db";
|
|
4
|
+
import { adsrc } from "./adsrc";
|
|
4
5
|
|
|
5
6
|
const needDrop = [
|
|
6
7
|
["DATETIME", "int2"],
|
|
@@ -16,6 +17,8 @@ const needUsing = [
|
|
|
16
17
|
];
|
|
17
18
|
const types = { int2: "SMALLINT", int4: "INTEGER", int8: "BIGINT", varchar: "VARCHAR" };
|
|
18
19
|
|
|
20
|
+
const actions: { [k in ForeignKeyActions]: string } = { cascade: "c", "no action": "a", restrict: "r", "set default": "d", "set null": "n" };
|
|
21
|
+
|
|
19
22
|
export class PGDB extends DB {
|
|
20
23
|
private client: PoolClient;
|
|
21
24
|
private indexes: string[];
|
|
@@ -38,17 +41,26 @@ export class PGDB extends DB {
|
|
|
38
41
|
|
|
39
42
|
async dropConstraints(table: Table): Promise<number[]> {
|
|
40
43
|
const indexes: number[] = [];
|
|
41
|
-
const res = await this.client.query("SELECT
|
|
44
|
+
const res = await this.client.query("SELECT confdeltype, confupdtype, conindid, conname, contype FROM pg_constraint WHERE conrelid = $1 ORDER BY conname", [table.oid]);
|
|
42
45
|
|
|
43
46
|
for(const row of res.rows) {
|
|
44
|
-
const
|
|
47
|
+
const arr = table.constraints.filter(_ => _.constraintName === row.conname && _.type === row.contype);
|
|
48
|
+
let drop = false;
|
|
49
|
+
|
|
50
|
+
if(arr.length === 0) drop = true;
|
|
51
|
+
else if(row.contype === "u") indexes.push(row.conindid);
|
|
52
|
+
else {
|
|
53
|
+
const { options } = arr[0].attribute.foreignKey;
|
|
45
54
|
|
|
46
|
-
|
|
55
|
+
if(actions[options.onDelete] !== row.confdeltype || actions[options.onUpdate] !== row.confupdtype) drop = true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if(drop) {
|
|
47
59
|
const statement = `ALTER TABLE ${table.tableName} DROP CONSTRAINT ${row.conname} CASCADE`;
|
|
48
60
|
|
|
49
|
-
this.
|
|
50
|
-
await this.client.query(statement);
|
|
51
|
-
}
|
|
61
|
+
this.syncLog(statement);
|
|
62
|
+
if(this.sync) await this.client.query(statement);
|
|
63
|
+
}
|
|
52
64
|
}
|
|
53
65
|
|
|
54
66
|
return indexes;
|
|
@@ -57,14 +69,14 @@ export class PGDB extends DB {
|
|
|
57
69
|
async dropField(tableName: string, fieldName: string): Promise<void> {
|
|
58
70
|
const statement = `ALTER TABLE ${tableName} DROP COLUMN ${fieldName}`;
|
|
59
71
|
|
|
60
|
-
this.
|
|
61
|
-
await this.client.query(statement);
|
|
72
|
+
this.syncLog(statement);
|
|
73
|
+
if(this.sync) await this.client.query(statement);
|
|
62
74
|
}
|
|
63
75
|
|
|
64
76
|
async dropFields(table: Table): Promise<void> {
|
|
65
77
|
const res = await this.client.query("SELECT attname FROM pg_attribute WHERE attrelid = $1 AND attnum > 0 AND attisdropped = false AND attinhcount = 0", [table.oid]);
|
|
66
78
|
|
|
67
|
-
for(const i in res.rows) if(table.
|
|
79
|
+
for(const i in res.rows) if(! table.findField(res.rows[i].attname)) await this.dropField(table.tableName, res.rows[i].attname);
|
|
68
80
|
}
|
|
69
81
|
|
|
70
82
|
async dropIndexes(table: Table, constraintIndexes: number[]): Promise<void> {
|
|
@@ -97,8 +109,8 @@ export class PGDB extends DB {
|
|
|
97
109
|
for(const index of Object.keys(iobject).sort()) {
|
|
98
110
|
const statement = `DROP INDEX ${index}`;
|
|
99
111
|
|
|
100
|
-
this.
|
|
101
|
-
await this.client.query(statement);
|
|
112
|
+
this.syncLog(statement);
|
|
113
|
+
if(this.sync) await this.client.query(statement);
|
|
102
114
|
}
|
|
103
115
|
}
|
|
104
116
|
|
|
@@ -126,11 +138,11 @@ export class PGDB extends DB {
|
|
|
126
138
|
throw new Error(`Unknown type: '${type}', '${size}'`);
|
|
127
139
|
}
|
|
128
140
|
|
|
129
|
-
async
|
|
141
|
+
async syncDataBase(): Promise<void> {
|
|
130
142
|
let err: Error;
|
|
131
143
|
|
|
132
144
|
try {
|
|
133
|
-
await super.
|
|
145
|
+
await super.syncDataBase();
|
|
134
146
|
} catch(e) {
|
|
135
147
|
err = e;
|
|
136
148
|
}
|
|
@@ -151,19 +163,18 @@ export class PGDB extends DB {
|
|
|
151
163
|
if(! res.rowCount) {
|
|
152
164
|
let query: string;
|
|
153
165
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
query = `
|
|
160
|
-
|
|
161
|
-
}
|
|
166
|
+
if(type === "f") {
|
|
167
|
+
const { fieldName, options, tableName } = attribute.foreignKey;
|
|
168
|
+
const onDelete = options.onDelete !== "no action" ? ` ON DELETE ${options.onDelete.toUpperCase()}` : "";
|
|
169
|
+
const onUpdate = options.onUpdate !== "no action" ? ` ON UPDATE ${options.onUpdate.toUpperCase()}` : "";
|
|
170
|
+
|
|
171
|
+
query = `FOREIGN KEY (${attribute.fieldName}) REFERENCES ${tableName}(${fieldName})${onDelete}${onUpdate}`;
|
|
172
|
+
} else query = `UNIQUE(${attribute.fieldName})`;
|
|
162
173
|
|
|
163
174
|
const statement = `ALTER TABLE ${table.tableName} ADD CONSTRAINT ${constraintName} ${query}`;
|
|
164
175
|
|
|
165
|
-
this.
|
|
166
|
-
await this.client.query(statement);
|
|
176
|
+
this.syncLog(statement);
|
|
177
|
+
if(this.sync) await this.client.query(statement);
|
|
167
178
|
}
|
|
168
179
|
}
|
|
169
180
|
}
|
|
@@ -175,26 +186,25 @@ export class PGDB extends DB {
|
|
|
175
186
|
const { fieldName, notNull, size } = attribute;
|
|
176
187
|
const defaultValue = attribute.defaultValue === undefined ? undefined : format("%L", attribute.defaultValue);
|
|
177
188
|
const [base, type] = this.fieldType(attribute);
|
|
189
|
+
const where = "attrelid = $1 AND attnum > 0 AND atttypid = pg_type.oid AND attislocal = 't' AND attname = $2";
|
|
178
190
|
|
|
179
191
|
const res = await this.client.query(
|
|
180
|
-
`SELECT attnotnull, atttypmod, typname, ${
|
|
181
|
-
this.version >= 12 ? "pg_get_expr(pg_attrdef.adbin, pg_attrdef.adrelid) AS adsrc" : "adsrc"
|
|
182
|
-
} FROM pg_type, pg_attribute LEFT JOIN pg_attrdef ON adrelid = attrelid AND adnum = attnum WHERE attrelid = $1 AND attnum > 0 AND atttypid = pg_type.oid AND attislocal = 't' AND attname = $2`,
|
|
192
|
+
`SELECT attnotnull, atttypmod, typname, ${adsrc(this.version)} FROM pg_type, pg_attribute LEFT JOIN pg_attrdef ON adrelid = attrelid AND adnum = attnum WHERE ${where}`,
|
|
183
193
|
[oid, fieldName]
|
|
184
194
|
);
|
|
185
195
|
|
|
186
196
|
const addField = async () => {
|
|
187
197
|
const statement = `ALTER TABLE ${tableName} ADD COLUMN ${fieldName} ${type}`;
|
|
188
198
|
|
|
189
|
-
this.
|
|
190
|
-
await this.client.query(statement);
|
|
199
|
+
this.syncLog(statement);
|
|
200
|
+
if(this.sync) await this.client.query(statement);
|
|
191
201
|
};
|
|
192
202
|
|
|
193
203
|
const dropDefault = async () => {
|
|
194
204
|
const statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} DROP DEFAULT`;
|
|
195
205
|
|
|
196
|
-
this.
|
|
197
|
-
await this.client.query(statement);
|
|
206
|
+
this.syncLog(statement);
|
|
207
|
+
if(this.sync) await this.client.query(statement);
|
|
198
208
|
};
|
|
199
209
|
|
|
200
210
|
const setNotNull = async (isNull: boolean) => {
|
|
@@ -202,22 +212,22 @@ export class PGDB extends DB {
|
|
|
202
212
|
|
|
203
213
|
const statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} ${notNull ? "SET" : "DROP"} NOT NULL`;
|
|
204
214
|
|
|
205
|
-
this.
|
|
206
|
-
await this.client.query(statement);
|
|
215
|
+
this.syncLog(statement);
|
|
216
|
+
if(this.sync) await this.client.query(statement);
|
|
207
217
|
};
|
|
208
218
|
|
|
209
219
|
const setDefault = async (isNull: boolean) => {
|
|
210
220
|
if(defaultValue !== undefined) {
|
|
211
221
|
let statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} SET DEFAULT ${defaultValue}`;
|
|
212
222
|
|
|
213
|
-
this.
|
|
214
|
-
await this.client.query(statement);
|
|
223
|
+
this.syncLog(statement);
|
|
224
|
+
if(this.sync) await this.client.query(statement);
|
|
215
225
|
|
|
216
226
|
if(isNull) {
|
|
217
227
|
statement = `UPDATE ${tableName} SET ${fieldName} = ${defaultValue} WHERE ${fieldName} IS NULL`;
|
|
218
228
|
|
|
219
|
-
this.
|
|
220
|
-
this.client.query(statement);
|
|
229
|
+
this.syncLog(statement);
|
|
230
|
+
if(this.sync) this.client.query(statement);
|
|
221
231
|
}
|
|
222
232
|
}
|
|
223
233
|
|
|
@@ -241,8 +251,8 @@ export class PGDB extends DB {
|
|
|
241
251
|
const using = needUsing.filter(([type, name]) => attribute.type === type && typname === name).length ? " USING " + fieldName + "::" + type : "";
|
|
242
252
|
const statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} TYPE ${type}${using}`;
|
|
243
253
|
|
|
244
|
-
this.
|
|
245
|
-
await this.client.query(statement);
|
|
254
|
+
this.syncLog(statement);
|
|
255
|
+
if(this.sync) await this.client.query(statement);
|
|
246
256
|
await setDefault(attnotnull);
|
|
247
257
|
}
|
|
248
258
|
} else if(defaultValue === undefined) {
|
|
@@ -262,8 +272,8 @@ export class PGDB extends DB {
|
|
|
262
272
|
if(! this.indexes.includes(indexName)) {
|
|
263
273
|
const statement = `CREATE${unique ? " UNIQUE" : ""} INDEX ${indexName} ON ${tableName} USING ${type} (${fields.join(", ")})`;
|
|
264
274
|
|
|
265
|
-
this.
|
|
266
|
-
await this.client.query(statement);
|
|
275
|
+
this.syncLog(statement);
|
|
276
|
+
if(this.sync) await this.client.query(statement);
|
|
267
277
|
}
|
|
268
278
|
}
|
|
269
279
|
}
|
|
@@ -273,8 +283,8 @@ export class PGDB extends DB {
|
|
|
273
283
|
|
|
274
284
|
const statement = `ALTER SEQUENCE ${table.tableName}_id_seq OWNED BY ${table.tableName}.id`;
|
|
275
285
|
|
|
276
|
-
this.
|
|
277
|
-
await this.client.query(statement);
|
|
286
|
+
this.syncLog(statement);
|
|
287
|
+
if(this.sync) await this.client.query(statement);
|
|
278
288
|
}
|
|
279
289
|
|
|
280
290
|
async syncTable(table: Table): Promise<void> {
|
|
@@ -287,8 +297,8 @@ export class PGDB extends DB {
|
|
|
287
297
|
if(e.code === "42P01") {
|
|
288
298
|
const statement = `CREATE SEQUENCE ${table.tableName}_id_seq`;
|
|
289
299
|
|
|
290
|
-
this.
|
|
291
|
-
await this.client.query(statement);
|
|
300
|
+
this.syncLog(statement);
|
|
301
|
+
if(this.sync) await this.client.query(statement);
|
|
292
302
|
table.autoIncrementOwn = true;
|
|
293
303
|
|
|
294
304
|
return;
|
|
@@ -310,7 +320,7 @@ export class PGDB extends DB {
|
|
|
310
320
|
|
|
311
321
|
if(resParent.rowCount) {
|
|
312
322
|
if(! table.parent) drop = true;
|
|
313
|
-
else if(this.
|
|
323
|
+
else if(this.findTable(table.parent.tableName).oid === resParent.rows[0].inhparent) return;
|
|
314
324
|
|
|
315
325
|
drop = true;
|
|
316
326
|
} else if(table.parent) drop = true;
|
|
@@ -319,8 +329,8 @@ export class PGDB extends DB {
|
|
|
319
329
|
const statement = `DROP TABLE ${table.tableName} CASCADE`;
|
|
320
330
|
|
|
321
331
|
create = true;
|
|
322
|
-
this.
|
|
323
|
-
await this.client.query(statement);
|
|
332
|
+
this.syncLog(statement);
|
|
333
|
+
if(this.sync) await this.client.query(statement);
|
|
324
334
|
}
|
|
325
335
|
} else create = true;
|
|
326
336
|
|
|
@@ -328,12 +338,12 @@ export class PGDB extends DB {
|
|
|
328
338
|
const parent = table.parent ? ` INHERITS (${table.parent.tableName})` : "";
|
|
329
339
|
const statement = `CREATE TABLE ${table.tableName} ()${parent}`;
|
|
330
340
|
|
|
331
|
-
this.
|
|
332
|
-
await this.client.query(statement);
|
|
341
|
+
this.syncLog(statement);
|
|
342
|
+
if(this.sync) await this.client.query(statement);
|
|
333
343
|
|
|
334
344
|
const resTable = await this.client.query("SELECT oid FROM pg_class WHERE relname = $1", [table.tableName]);
|
|
335
345
|
|
|
336
|
-
table.oid = resTable.rows[0]
|
|
346
|
+
table.oid = resTable.rows[0]?.oid;
|
|
337
347
|
}
|
|
338
348
|
}
|
|
339
349
|
}
|
package/package.json
CHANGED
|
@@ -6,26 +6,29 @@
|
|
|
6
6
|
"@types/pg-format": "1.0.2",
|
|
7
7
|
"pg": "8.7.1",
|
|
8
8
|
"pg-format": "1.0.4",
|
|
9
|
-
"sedentary": "0.0.
|
|
9
|
+
"sedentary": "0.0.18"
|
|
10
10
|
},
|
|
11
11
|
"description": "The ORM which never needs to migrate - PostgreSQL",
|
|
12
12
|
"devDependencies": {
|
|
13
13
|
"@types/mocha": "9.0.0",
|
|
14
|
-
"@types/node": "16.11.
|
|
14
|
+
"@types/node": "16.11.10",
|
|
15
15
|
"@types/yamljs": "0.2.31",
|
|
16
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
17
|
-
"@typescript-eslint/parser": "5.
|
|
18
|
-
"eslint": "8.
|
|
16
|
+
"@typescript-eslint/eslint-plugin": "5.4.0",
|
|
17
|
+
"@typescript-eslint/parser": "5.4.0",
|
|
18
|
+
"eslint": "8.3.0",
|
|
19
19
|
"mocha": "9.1.3",
|
|
20
20
|
"nyc": "15.1.0",
|
|
21
|
-
"prettier": "2.
|
|
21
|
+
"prettier": "2.5.0",
|
|
22
22
|
"ts-node": "10.4.0",
|
|
23
|
-
"typescript": "4.
|
|
23
|
+
"typescript": "4.5.2",
|
|
24
24
|
"yamljs": "0.3.0"
|
|
25
25
|
},
|
|
26
26
|
"engines": {
|
|
27
27
|
"node": ">=12.0"
|
|
28
28
|
},
|
|
29
|
+
"funding": {
|
|
30
|
+
"url": "https://blockchain.info/address/1Md9WFAHrXTb3yPBwQWmUfv2RmzrtbHioB"
|
|
31
|
+
},
|
|
29
32
|
"homepage": "https://github.com/iccicci/sedentary-pg#readme",
|
|
30
33
|
"keywords": [
|
|
31
34
|
"DB",
|
|
@@ -59,5 +62,5 @@
|
|
|
59
62
|
"version": "node -r ts-node/register utils.ts version"
|
|
60
63
|
},
|
|
61
64
|
"types": "index.d.ts",
|
|
62
|
-
"version": "0.0.
|
|
65
|
+
"version": "0.0.18"
|
|
63
66
|
}
|