sedentary-pg 0.0.13 → 0.0.14
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/index.d.ts +4 -1
- package/lib/pgdb.d.ts +4 -4
- package/lib/pgdb.js +70 -73
- package/lib/pgdb.ts +76 -78
- package/package.json +2 -2
package/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { SchemaOptions, Sedentary } from "sedentary";
|
|
1
|
+
import { SchemaOptions as SedentarySchemaOptions, Sedentary } from "sedentary";
|
|
2
2
|
import { PoolConfig } from "pg";
|
|
3
|
+
export interface SchemaOptions extends SedentarySchemaOptions {
|
|
4
|
+
serverless?: boolean;
|
|
5
|
+
}
|
|
3
6
|
export declare class SedentaryPG extends Sedentary {
|
|
4
7
|
constructor(connection: PoolConfig, options?: SchemaOptions);
|
|
5
8
|
}
|
package/lib/pgdb.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PoolConfig } from "pg";
|
|
2
|
-
import {
|
|
2
|
+
import { Attribute, DB, Natural, Table } from "sedentary/lib/db";
|
|
3
3
|
export declare class PGDB extends DB {
|
|
4
4
|
private client;
|
|
5
5
|
private indexes;
|
|
@@ -7,12 +7,12 @@ export declare class PGDB extends DB {
|
|
|
7
7
|
private version;
|
|
8
8
|
constructor(connection: PoolConfig, log: (message: string) => void);
|
|
9
9
|
connect(): Promise<void>;
|
|
10
|
-
dropConstraints(table: Table): Promise<
|
|
10
|
+
dropConstraints(table: Table): Promise<number[]>;
|
|
11
11
|
dropField(tableName: string, fieldName: string): Promise<void>;
|
|
12
12
|
dropFields(table: Table): Promise<void>;
|
|
13
|
-
dropIndexes(table: Table): Promise<void>;
|
|
13
|
+
dropIndexes(table: Table, constraintIndexes: number[]): Promise<void>;
|
|
14
14
|
end(): Promise<void>;
|
|
15
|
-
fieldType(
|
|
15
|
+
fieldType(attribute: Attribute<Natural, unknown>): string[];
|
|
16
16
|
sync(): Promise<void>;
|
|
17
17
|
syncConstraints(table: Table): Promise<void>;
|
|
18
18
|
syncFields(table: Table): Promise<void>;
|
package/lib/pgdb.js
CHANGED
|
@@ -31,34 +31,19 @@ class PGDB extends db_1.DB {
|
|
|
31
31
|
this.version = parseInt(res.rows[0].version.split(" ")[1].split(".")[0], 10);
|
|
32
32
|
}
|
|
33
33
|
async dropConstraints(table) {
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return;
|
|
46
|
-
/*
|
|
47
|
-
return pgo.client.query("SELECT conindid FROM pg_attribute, pg_constraint WHERE attrelid = $1 AND conrelid = $1 AND attnum = conkey[1]", [table.oid], function(err, res) {
|
|
48
|
-
const arr = [];
|
|
49
|
-
|
|
50
|
-
if(pgo.error(err, 1011, table.name)) return;
|
|
51
|
-
|
|
52
|
-
for(const i in res.rows) arr.push(res.rows[i].conindid);
|
|
53
|
-
|
|
54
|
-
dropIndex(pgo, arr);
|
|
55
|
-
});
|
|
56
|
-
*/
|
|
57
|
-
for (const i in res.rows) {
|
|
58
|
-
const statement = `ALTER TABLE ${table.tableName} DROP CONSTRAINT ${res.rows[i].conname}`;
|
|
59
|
-
this.log(statement);
|
|
60
|
-
await this.client.query(statement);
|
|
34
|
+
const indexes = [];
|
|
35
|
+
const res = await this.client.query("SELECT * FROM pg_constraint WHERE conrelid = $1 ORDER BY conname", [table.oid]);
|
|
36
|
+
for (const row of res.rows) {
|
|
37
|
+
const constraint = table.constraints.filter(_ => _.constraintName === row.conname);
|
|
38
|
+
if (constraint.length === 0) {
|
|
39
|
+
const statement = `ALTER TABLE ${table.tableName} DROP CONSTRAINT ${row.conname} CASCADE`;
|
|
40
|
+
this.log(statement);
|
|
41
|
+
await this.client.query(statement);
|
|
42
|
+
}
|
|
43
|
+
else
|
|
44
|
+
indexes.push(row.conindid);
|
|
61
45
|
}
|
|
46
|
+
return indexes;
|
|
62
47
|
}
|
|
63
48
|
async dropField(tableName, fieldName) {
|
|
64
49
|
const statement = `ALTER TABLE ${tableName} DROP COLUMN ${fieldName}`;
|
|
@@ -68,26 +53,28 @@ class PGDB extends db_1.DB {
|
|
|
68
53
|
async dropFields(table) {
|
|
69
54
|
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]);
|
|
70
55
|
for (const i in res.rows)
|
|
71
|
-
if (table.
|
|
56
|
+
if (table.attributes.filter(f => f.fieldName === res.rows[i].attname).length === 0)
|
|
72
57
|
await this.dropField(table.tableName, res.rows[i].attname);
|
|
73
58
|
}
|
|
74
|
-
async dropIndexes(table) {
|
|
59
|
+
async dropIndexes(table, constraintIndexes) {
|
|
75
60
|
const { indexes, oid } = table;
|
|
76
61
|
const iobject = {};
|
|
77
|
-
const res = await this.client.query("SELECT amname, attname, indisunique, relname FROM pg_class, pg_index, pg_attribute, pg_am WHERE indrelid = $1 AND indexrelid = pg_class.oid AND attrelid = pg_class.oid AND relam = pg_am.oid ORDER BY attnum", [oid]);
|
|
62
|
+
const res = await this.client.query("SELECT amname, attname, indexrelid, indisunique, relname FROM pg_class, pg_index, pg_attribute, pg_am WHERE indrelid = $1 AND indexrelid = pg_class.oid AND attrelid = pg_class.oid AND relam = pg_am.oid ORDER BY attnum", [oid]);
|
|
78
63
|
for (const row of res.rows) {
|
|
79
|
-
const { amname, attname, indisunique, relname } = row;
|
|
80
|
-
if (
|
|
81
|
-
iobject[relname]
|
|
82
|
-
|
|
83
|
-
|
|
64
|
+
const { amname, attname, indexrelid, indisunique, relname } = row;
|
|
65
|
+
if (!constraintIndexes.includes(indexrelid)) {
|
|
66
|
+
if (iobject[relname])
|
|
67
|
+
iobject[relname].fields.push(attname);
|
|
68
|
+
else
|
|
69
|
+
iobject[relname] = { fields: [attname], indexName: relname, type: amname, unique: indisunique };
|
|
70
|
+
}
|
|
84
71
|
}
|
|
85
72
|
this.indexes = [];
|
|
86
73
|
for (const index of indexes) {
|
|
87
|
-
const {
|
|
88
|
-
if (iobject[
|
|
89
|
-
this.indexes.push(
|
|
90
|
-
delete iobject[
|
|
74
|
+
const { indexName } = index;
|
|
75
|
+
if (iobject[indexName] && this.indexesEq(index, iobject[indexName])) {
|
|
76
|
+
this.indexes.push(indexName);
|
|
77
|
+
delete iobject[indexName];
|
|
91
78
|
}
|
|
92
79
|
}
|
|
93
80
|
for (const index of Object.keys(iobject).sort()) {
|
|
@@ -99,8 +86,8 @@ class PGDB extends db_1.DB {
|
|
|
99
86
|
async end() {
|
|
100
87
|
await this.pool.end();
|
|
101
88
|
}
|
|
102
|
-
fieldType(
|
|
103
|
-
const { size, type } =
|
|
89
|
+
fieldType(attribute) {
|
|
90
|
+
const { size, type } = attribute;
|
|
104
91
|
let ret;
|
|
105
92
|
switch (type) {
|
|
106
93
|
case "DATETIME":
|
|
@@ -128,26 +115,35 @@ class PGDB extends db_1.DB {
|
|
|
128
115
|
throw err;
|
|
129
116
|
}
|
|
130
117
|
async syncConstraints(table) {
|
|
131
|
-
for (const
|
|
132
|
-
const
|
|
118
|
+
for (const constraint of table.constraints) {
|
|
119
|
+
const { attribute, constraintName, type } = constraint;
|
|
133
120
|
const res = await this.client.query("SELECT attname FROM pg_attribute, pg_constraint WHERE attrelid = $1 AND conrelid = $1 AND attnum = conkey[1] AND attname = $2", [
|
|
134
121
|
table.oid,
|
|
135
|
-
|
|
122
|
+
attribute.fieldName
|
|
136
123
|
]);
|
|
137
124
|
if (!res.rowCount) {
|
|
138
|
-
|
|
125
|
+
let query;
|
|
126
|
+
switch (type) {
|
|
127
|
+
case "f":
|
|
128
|
+
query = `FOREIGN KEY (${attribute.fieldName}) REFERENCES ${attribute.foreignKey.tableName}(${attribute.foreignKey.fieldName})`;
|
|
129
|
+
break;
|
|
130
|
+
case "u":
|
|
131
|
+
query = `UNIQUE(${attribute.fieldName})`;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
const statement = `ALTER TABLE ${table.tableName} ADD CONSTRAINT ${constraintName} ${query}`;
|
|
139
135
|
this.log(statement);
|
|
140
136
|
await this.client.query(statement);
|
|
141
137
|
}
|
|
142
138
|
}
|
|
143
139
|
}
|
|
144
140
|
async syncFields(table) {
|
|
145
|
-
const {
|
|
146
|
-
for (const
|
|
147
|
-
const { fieldName, notNull, size } =
|
|
148
|
-
const defaultValue =
|
|
149
|
-
const [base, type] = this.fieldType(
|
|
150
|
-
const res = await this.client.query(`SELECT
|
|
141
|
+
const { attributes, oid, tableName } = table;
|
|
142
|
+
for (const attribute of attributes) {
|
|
143
|
+
const { fieldName, notNull, size } = attribute;
|
|
144
|
+
const defaultValue = attribute.defaultValue === undefined ? undefined : (0, pg_format_1.default)("%L", attribute.defaultValue);
|
|
145
|
+
const [base, type] = this.fieldType(attribute);
|
|
146
|
+
const res = await this.client.query(`SELECT attnotnull, atttypmod, typname, ${this.version >= 12 ? "pg_get_expr(pg_attrdef.adbin, pg_attrdef.adrelid) AS adsrc" : "adsrc"} 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`, [oid, fieldName]);
|
|
151
147
|
const addField = async () => {
|
|
152
148
|
const statement = `ALTER TABLE ${tableName} ADD COLUMN ${fieldName} ${type}`;
|
|
153
149
|
this.log(statement);
|
|
@@ -158,13 +154,6 @@ class PGDB extends db_1.DB {
|
|
|
158
154
|
this.log(statement);
|
|
159
155
|
await this.client.query(statement);
|
|
160
156
|
};
|
|
161
|
-
const setDefault = async () => {
|
|
162
|
-
if (defaultValue === undefined)
|
|
163
|
-
return;
|
|
164
|
-
const statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} SET DEFAULT ${defaultValue}`;
|
|
165
|
-
this.log(statement);
|
|
166
|
-
await this.client.query(statement);
|
|
167
|
-
};
|
|
168
157
|
const setNotNull = async (isNull) => {
|
|
169
158
|
if (isNull === notNull)
|
|
170
159
|
return;
|
|
@@ -172,29 +161,39 @@ class PGDB extends db_1.DB {
|
|
|
172
161
|
this.log(statement);
|
|
173
162
|
await this.client.query(statement);
|
|
174
163
|
};
|
|
164
|
+
const setDefault = async (isNull) => {
|
|
165
|
+
if (defaultValue !== undefined) {
|
|
166
|
+
let statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} SET DEFAULT ${defaultValue}`;
|
|
167
|
+
this.log(statement);
|
|
168
|
+
await this.client.query(statement);
|
|
169
|
+
if (isNull) {
|
|
170
|
+
statement = `UPDATE ${tableName} SET ${fieldName} = ${defaultValue} WHERE ${fieldName} IS NULL`;
|
|
171
|
+
this.log(statement);
|
|
172
|
+
this.client.query(statement);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
await setNotNull(isNull);
|
|
176
|
+
};
|
|
175
177
|
if (!res.rowCount) {
|
|
176
178
|
await addField();
|
|
177
|
-
await setDefault();
|
|
178
|
-
await setNotNull(false);
|
|
179
|
+
await setDefault(false);
|
|
179
180
|
}
|
|
180
181
|
else {
|
|
181
182
|
const { adsrc, attnotnull, atttypmod, typname } = res.rows[0];
|
|
182
183
|
if (types[typname] !== base || (base === "VARCHAR" && (size ? size + 4 !== atttypmod : atttypmod !== -1))) {
|
|
183
|
-
if (needDrop.filter(([type, name]) =>
|
|
184
|
+
if (needDrop.filter(([type, name]) => attribute.type === type && typname === name).length) {
|
|
184
185
|
await this.dropField(tableName, fieldName);
|
|
185
186
|
await addField();
|
|
186
|
-
await setDefault();
|
|
187
|
-
await setNotNull(false);
|
|
187
|
+
await setDefault(false);
|
|
188
188
|
}
|
|
189
189
|
else {
|
|
190
190
|
if (adsrc)
|
|
191
191
|
dropDefault();
|
|
192
|
-
const using = needUsing.filter(([type, name]) =>
|
|
192
|
+
const using = needUsing.filter(([type, name]) => attribute.type === type && typname === name).length ? " USING " + fieldName + "::" + type : "";
|
|
193
193
|
const statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} TYPE ${type}${using}`;
|
|
194
194
|
this.log(statement);
|
|
195
195
|
await this.client.query(statement);
|
|
196
|
-
await setDefault();
|
|
197
|
-
await setNotNull(attnotnull);
|
|
196
|
+
await setDefault(attnotnull);
|
|
198
197
|
}
|
|
199
198
|
}
|
|
200
199
|
else if (defaultValue === undefined) {
|
|
@@ -202,19 +201,17 @@ class PGDB extends db_1.DB {
|
|
|
202
201
|
dropDefault();
|
|
203
202
|
await setNotNull(attnotnull);
|
|
204
203
|
}
|
|
205
|
-
else if (!adsrc || adsrc.split("::")[0] !== defaultValue)
|
|
206
|
-
await setDefault();
|
|
207
|
-
await setNotNull(attnotnull);
|
|
208
|
-
}
|
|
204
|
+
else if (!adsrc || adsrc.split("::")[0] !== defaultValue)
|
|
205
|
+
await setDefault(attnotnull);
|
|
209
206
|
}
|
|
210
207
|
}
|
|
211
208
|
}
|
|
212
209
|
async syncIndexes(table) {
|
|
213
210
|
const { indexes, tableName } = table;
|
|
214
211
|
for (const index of indexes) {
|
|
215
|
-
const { fields,
|
|
216
|
-
if (this.indexes.
|
|
217
|
-
const statement = `CREATE${unique ? " UNIQUE" : ""} INDEX ${
|
|
212
|
+
const { fields, indexName, type, unique } = index;
|
|
213
|
+
if (!this.indexes.includes(indexName)) {
|
|
214
|
+
const statement = `CREATE${unique ? " UNIQUE" : ""} INDEX ${indexName} ON ${tableName} USING ${type} (${fields.join(", ")})`;
|
|
218
215
|
this.log(statement);
|
|
219
216
|
await this.client.query(statement);
|
|
220
217
|
}
|
package/lib/pgdb.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Pool, PoolClient, PoolConfig } from "pg";
|
|
2
2
|
import format from "pg-format";
|
|
3
|
-
import {
|
|
3
|
+
import { Attribute, DB, Index, Natural, Table } from "sedentary/lib/db";
|
|
4
4
|
|
|
5
5
|
const needDrop = [
|
|
6
6
|
["DATETIME", "int2"],
|
|
@@ -36,39 +36,22 @@ export class PGDB extends DB {
|
|
|
36
36
|
this.version = parseInt(res.rows[0].version.split(" ")[1].split(".")[0], 10);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
async dropConstraints(table: Table): Promise<
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
const values: (number | string)[] = [table.oid];
|
|
43
|
-
const wheres = [];
|
|
39
|
+
async dropConstraints(table: Table): Promise<number[]> {
|
|
40
|
+
const indexes: number[] = [];
|
|
41
|
+
const res = await this.client.query("SELECT * FROM pg_constraint WHERE conrelid = $1 ORDER BY conname", [table.oid]);
|
|
44
42
|
|
|
45
|
-
for(const
|
|
46
|
-
|
|
47
|
-
values.push(table.constraints[i].type);
|
|
48
|
-
values.push(table.constraints[i].field);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const res = await this.client.query(query + wheres.join(""), values);
|
|
52
|
-
|
|
53
|
-
if(! res.rowCount) return;
|
|
54
|
-
/*
|
|
55
|
-
return pgo.client.query("SELECT conindid FROM pg_attribute, pg_constraint WHERE attrelid = $1 AND conrelid = $1 AND attnum = conkey[1]", [table.oid], function(err, res) {
|
|
56
|
-
const arr = [];
|
|
57
|
-
|
|
58
|
-
if(pgo.error(err, 1011, table.name)) return;
|
|
59
|
-
|
|
60
|
-
for(const i in res.rows) arr.push(res.rows[i].conindid);
|
|
61
|
-
|
|
62
|
-
dropIndex(pgo, arr);
|
|
63
|
-
});
|
|
64
|
-
*/
|
|
43
|
+
for(const row of res.rows) {
|
|
44
|
+
const constraint = table.constraints.filter(_ => _.constraintName === row.conname);
|
|
65
45
|
|
|
66
|
-
|
|
67
|
-
|
|
46
|
+
if(constraint.length === 0) {
|
|
47
|
+
const statement = `ALTER TABLE ${table.tableName} DROP CONSTRAINT ${row.conname} CASCADE`;
|
|
68
48
|
|
|
69
|
-
|
|
70
|
-
|
|
49
|
+
this.log(statement);
|
|
50
|
+
await this.client.query(statement);
|
|
51
|
+
} else indexes.push(row.conindid);
|
|
71
52
|
}
|
|
53
|
+
|
|
54
|
+
return indexes;
|
|
72
55
|
}
|
|
73
56
|
|
|
74
57
|
async dropField(tableName: string, fieldName: string): Promise<void> {
|
|
@@ -81,31 +64,33 @@ export class PGDB extends DB {
|
|
|
81
64
|
async dropFields(table: Table): Promise<void> {
|
|
82
65
|
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]);
|
|
83
66
|
|
|
84
|
-
for(const i in res.rows) if(table.
|
|
67
|
+
for(const i in res.rows) if(table.attributes.filter(f => f.fieldName === res.rows[i].attname).length === 0) await this.dropField(table.tableName, res.rows[i].attname);
|
|
85
68
|
}
|
|
86
69
|
|
|
87
|
-
async dropIndexes(table: Table): Promise<void> {
|
|
70
|
+
async dropIndexes(table: Table, constraintIndexes: number[]): Promise<void> {
|
|
88
71
|
const { indexes, oid } = table;
|
|
89
|
-
const iobject: { [key: string]:
|
|
72
|
+
const iobject: { [key: string]: Index } = {};
|
|
90
73
|
const res = await this.client.query(
|
|
91
|
-
"SELECT amname, attname, indisunique, relname FROM pg_class, pg_index, pg_attribute, pg_am WHERE indrelid = $1 AND indexrelid = pg_class.oid AND attrelid = pg_class.oid AND relam = pg_am.oid ORDER BY attnum",
|
|
74
|
+
"SELECT amname, attname, indexrelid, indisunique, relname FROM pg_class, pg_index, pg_attribute, pg_am WHERE indrelid = $1 AND indexrelid = pg_class.oid AND attrelid = pg_class.oid AND relam = pg_am.oid ORDER BY attnum",
|
|
92
75
|
[oid]
|
|
93
76
|
);
|
|
94
77
|
|
|
95
78
|
for(const row of res.rows) {
|
|
96
|
-
const { amname, attname, indisunique, relname } = row;
|
|
79
|
+
const { amname, attname, indexrelid, indisunique, relname } = row;
|
|
97
80
|
|
|
98
|
-
if(
|
|
99
|
-
|
|
81
|
+
if(! constraintIndexes.includes(indexrelid)) {
|
|
82
|
+
if(iobject[relname]) iobject[relname].fields.push(attname);
|
|
83
|
+
else iobject[relname] = { fields: [attname], indexName: relname, type: amname, unique: indisunique };
|
|
84
|
+
}
|
|
100
85
|
}
|
|
101
86
|
|
|
102
87
|
this.indexes = [];
|
|
103
88
|
for(const index of indexes) {
|
|
104
|
-
const {
|
|
89
|
+
const { indexName } = index;
|
|
105
90
|
|
|
106
|
-
if(iobject[
|
|
107
|
-
this.indexes.push(
|
|
108
|
-
delete iobject[
|
|
91
|
+
if(iobject[indexName] && this.indexesEq(index, iobject[indexName])) {
|
|
92
|
+
this.indexes.push(indexName);
|
|
93
|
+
delete iobject[indexName];
|
|
109
94
|
}
|
|
110
95
|
}
|
|
111
96
|
|
|
@@ -121,8 +106,8 @@ export class PGDB extends DB {
|
|
|
121
106
|
await this.pool.end();
|
|
122
107
|
}
|
|
123
108
|
|
|
124
|
-
fieldType(
|
|
125
|
-
const { size, type } =
|
|
109
|
+
fieldType(attribute: Attribute<Natural, unknown>): string[] {
|
|
110
|
+
const { size, type } = attribute;
|
|
126
111
|
let ret;
|
|
127
112
|
|
|
128
113
|
switch(type) {
|
|
@@ -156,16 +141,26 @@ export class PGDB extends DB {
|
|
|
156
141
|
}
|
|
157
142
|
|
|
158
143
|
async syncConstraints(table: Table): Promise<void> {
|
|
159
|
-
for(const
|
|
160
|
-
const
|
|
161
|
-
|
|
144
|
+
for(const constraint of table.constraints) {
|
|
145
|
+
const { attribute, constraintName, type } = constraint;
|
|
162
146
|
const res = await this.client.query("SELECT attname FROM pg_attribute, pg_constraint WHERE attrelid = $1 AND conrelid = $1 AND attnum = conkey[1] AND attname = $2", [
|
|
163
147
|
table.oid,
|
|
164
|
-
|
|
148
|
+
attribute.fieldName
|
|
165
149
|
]);
|
|
166
150
|
|
|
167
151
|
if(! res.rowCount) {
|
|
168
|
-
|
|
152
|
+
let query: string;
|
|
153
|
+
|
|
154
|
+
switch(type) {
|
|
155
|
+
case "f":
|
|
156
|
+
query = `FOREIGN KEY (${attribute.fieldName}) REFERENCES ${attribute.foreignKey.tableName}(${attribute.foreignKey.fieldName})`;
|
|
157
|
+
break;
|
|
158
|
+
case "u":
|
|
159
|
+
query = `UNIQUE(${attribute.fieldName})`;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const statement = `ALTER TABLE ${table.tableName} ADD CONSTRAINT ${constraintName} ${query}`;
|
|
169
164
|
|
|
170
165
|
this.log(statement);
|
|
171
166
|
await this.client.query(statement);
|
|
@@ -174,16 +169,16 @@ export class PGDB extends DB {
|
|
|
174
169
|
}
|
|
175
170
|
|
|
176
171
|
async syncFields(table: Table): Promise<void> {
|
|
177
|
-
const {
|
|
172
|
+
const { attributes, oid, tableName } = table;
|
|
178
173
|
|
|
179
|
-
for(const
|
|
180
|
-
const { fieldName, notNull, size } =
|
|
181
|
-
const defaultValue =
|
|
182
|
-
const [base, type] = this.fieldType(
|
|
174
|
+
for(const attribute of attributes) {
|
|
175
|
+
const { fieldName, notNull, size } = attribute;
|
|
176
|
+
const defaultValue = attribute.defaultValue === undefined ? undefined : format("%L", attribute.defaultValue);
|
|
177
|
+
const [base, type] = this.fieldType(attribute);
|
|
183
178
|
|
|
184
179
|
const res = await this.client.query(
|
|
185
|
-
`SELECT
|
|
186
|
-
this.version >= 12 ? "
|
|
180
|
+
`SELECT attnotnull, atttypmod, typname, ${
|
|
181
|
+
this.version >= 12 ? "pg_get_expr(pg_attrdef.adbin, pg_attrdef.adrelid) AS adsrc" : "adsrc"
|
|
187
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`,
|
|
188
183
|
[oid, fieldName]
|
|
189
184
|
);
|
|
@@ -202,55 +197,58 @@ export class PGDB extends DB {
|
|
|
202
197
|
await this.client.query(statement);
|
|
203
198
|
};
|
|
204
199
|
|
|
205
|
-
const
|
|
206
|
-
if(
|
|
200
|
+
const setNotNull = async (isNull: boolean) => {
|
|
201
|
+
if(isNull === notNull) return;
|
|
207
202
|
|
|
208
|
-
const statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} SET
|
|
203
|
+
const statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} ${notNull ? "SET" : "DROP"} NOT NULL`;
|
|
209
204
|
|
|
210
205
|
this.log(statement);
|
|
211
206
|
await this.client.query(statement);
|
|
212
207
|
};
|
|
213
208
|
|
|
214
|
-
const
|
|
215
|
-
if(
|
|
209
|
+
const setDefault = async (isNull: boolean) => {
|
|
210
|
+
if(defaultValue !== undefined) {
|
|
211
|
+
let statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} SET DEFAULT ${defaultValue}`;
|
|
216
212
|
|
|
217
|
-
|
|
213
|
+
this.log(statement);
|
|
214
|
+
await this.client.query(statement);
|
|
218
215
|
|
|
219
|
-
|
|
220
|
-
|
|
216
|
+
if(isNull) {
|
|
217
|
+
statement = `UPDATE ${tableName} SET ${fieldName} = ${defaultValue} WHERE ${fieldName} IS NULL`;
|
|
218
|
+
|
|
219
|
+
this.log(statement);
|
|
220
|
+
this.client.query(statement);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
await setNotNull(isNull);
|
|
221
225
|
};
|
|
222
226
|
|
|
223
227
|
if(! res.rowCount) {
|
|
224
228
|
await addField();
|
|
225
|
-
await setDefault();
|
|
226
|
-
await setNotNull(false);
|
|
229
|
+
await setDefault(false);
|
|
227
230
|
} else {
|
|
228
231
|
const { adsrc, attnotnull, atttypmod, typname } = res.rows[0];
|
|
229
232
|
|
|
230
233
|
if(types[typname] !== base || (base === "VARCHAR" && (size ? size + 4 !== atttypmod : atttypmod !== -1))) {
|
|
231
|
-
if(needDrop.filter(([type, name]) =>
|
|
234
|
+
if(needDrop.filter(([type, name]) => attribute.type === type && typname === name).length) {
|
|
232
235
|
await this.dropField(tableName, fieldName);
|
|
233
236
|
await addField();
|
|
234
|
-
await setDefault();
|
|
235
|
-
await setNotNull(false);
|
|
237
|
+
await setDefault(false);
|
|
236
238
|
} else {
|
|
237
239
|
if(adsrc) dropDefault();
|
|
238
240
|
|
|
239
|
-
const using = needUsing.filter(([type, name]) =>
|
|
241
|
+
const using = needUsing.filter(([type, name]) => attribute.type === type && typname === name).length ? " USING " + fieldName + "::" + type : "";
|
|
240
242
|
const statement = `ALTER TABLE ${tableName} ALTER COLUMN ${fieldName} TYPE ${type}${using}`;
|
|
241
243
|
|
|
242
244
|
this.log(statement);
|
|
243
245
|
await this.client.query(statement);
|
|
244
|
-
await setDefault();
|
|
245
|
-
await setNotNull(attnotnull);
|
|
246
|
+
await setDefault(attnotnull);
|
|
246
247
|
}
|
|
247
248
|
} else if(defaultValue === undefined) {
|
|
248
249
|
if(adsrc) dropDefault();
|
|
249
250
|
await setNotNull(attnotnull);
|
|
250
|
-
} else if(! adsrc || adsrc.split("::")[0] !== defaultValue)
|
|
251
|
-
await setDefault();
|
|
252
|
-
await setNotNull(attnotnull);
|
|
253
|
-
}
|
|
251
|
+
} else if(! adsrc || adsrc.split("::")[0] !== defaultValue) await setDefault(attnotnull);
|
|
254
252
|
}
|
|
255
253
|
}
|
|
256
254
|
}
|
|
@@ -259,10 +257,10 @@ export class PGDB extends DB {
|
|
|
259
257
|
const { indexes, tableName } = table;
|
|
260
258
|
|
|
261
259
|
for(const index of indexes) {
|
|
262
|
-
const { fields,
|
|
260
|
+
const { fields, indexName, type, unique } = index;
|
|
263
261
|
|
|
264
|
-
if(this.indexes.
|
|
265
|
-
const statement = `CREATE${unique ? " UNIQUE" : ""} INDEX ${
|
|
262
|
+
if(! this.indexes.includes(indexName)) {
|
|
263
|
+
const statement = `CREATE${unique ? " UNIQUE" : ""} INDEX ${indexName} ON ${tableName} USING ${type} (${fields.join(", ")})`;
|
|
266
264
|
|
|
267
265
|
this.log(statement);
|
|
268
266
|
await this.client.query(statement);
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
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.14"
|
|
10
10
|
},
|
|
11
11
|
"description": "The ORM which never needs to migrate - PostgreSQL",
|
|
12
12
|
"devDependencies": {
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"version": "node -r ts-node/register utils.ts version"
|
|
60
60
|
},
|
|
61
61
|
"types": "index.d.ts",
|
|
62
|
-
"version": "0.0.
|
|
62
|
+
"version": "0.0.14"
|
|
63
63
|
}
|