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 CHANGED
@@ -29,4 +29,49 @@
29
29
 
30
30
  # under development
31
31
 
32
- https://bucardo.org/postgres_all_versions.html
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 { SchemaOptions as SedentarySchemaOptions, Sedentary } from "sedentary";
1
+ import { Entry, ForeignKeyOptions, Natural, SedentaryOptions, Sedentary, Type } from "sedentary";
2
2
  import { PoolConfig } from "pg";
3
- export interface SchemaOptions extends SedentarySchemaOptions {
4
- serverless?: boolean;
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?: SchemaOptions);
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
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.adsrc = void 0;
4
+ function adsrc(version) {
5
+ return version >= 12 ? "pg_get_expr(pg_attrdef.adbin, pg_attrdef.adrelid) AS adsrc" : "adsrc";
6
+ }
7
+ exports.adsrc = adsrc;
package/lib/adsrc.ts ADDED
@@ -0,0 +1,3 @@
1
+ export function adsrc(version: number) {
2
+ return version >= 12 ? "pg_get_expr(pg_attrdef.adbin, pg_attrdef.adrelid) AS adsrc" : "adsrc";
3
+ }
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
- sync(): Promise<void>;
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 * FROM pg_constraint WHERE conrelid = $1 ORDER BY conname", [table.oid]);
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 constraint = table.constraints.filter(_ => _.constraintName === row.conname);
38
- if (constraint.length === 0) {
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.log(statement);
41
- await this.client.query(statement);
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.log(statement);
51
- await this.client.query(statement);
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.attributes.filter(f => f.fieldName === res.rows[i].attname).length === 0)
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.log(statement);
83
- await this.client.query(statement);
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 sync() {
118
+ async syncDataBase() {
106
119
  let err;
107
120
  try {
108
- await super.sync();
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
- 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;
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.log(statement);
136
- await this.client.query(statement);
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 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]);
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.log(statement);
150
- await this.client.query(statement);
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.log(statement);
155
- await this.client.query(statement);
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.log(statement);
162
- await this.client.query(statement);
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.log(statement);
168
- await this.client.query(statement);
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.log(statement);
172
- this.client.query(statement);
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.log(statement);
195
- await this.client.query(statement);
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.log(statement);
216
- await this.client.query(statement);
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.log(statement);
225
- await this.client.query(statement);
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.log(statement);
239
- await this.client.query(statement);
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.tables[table.parent.tableName].oid === resParent.rows[0].inhparent)
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.log(statement);
266
- await this.client.query(statement);
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.log(statement);
275
- await this.client.query(statement);
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 * FROM pg_constraint WHERE conrelid = $1 ORDER BY conname", [table.oid]);
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 constraint = table.constraints.filter(_ => _.constraintName === row.conname);
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
- if(constraint.length === 0) {
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.log(statement);
50
- await this.client.query(statement);
51
- } else indexes.push(row.conindid);
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.log(statement);
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.attributes.filter(f => f.fieldName === res.rows[i].attname).length === 0) await this.dropField(table.tableName, res.rows[i].attname);
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.log(statement);
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 sync(): Promise<void> {
141
+ async syncDataBase(): Promise<void> {
130
142
  let err: Error;
131
143
 
132
144
  try {
133
- await super.sync();
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
- 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
- }
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.log(statement);
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.log(statement);
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.log(statement);
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.log(statement);
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.log(statement);
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.log(statement);
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.log(statement);
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.log(statement);
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.log(statement);
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.log(statement);
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.tables[table.parent.tableName].oid === resParent.rows[0].inhparent) return;
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.log(statement);
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.log(statement);
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].oid;
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.14"
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.7",
14
+ "@types/node": "16.11.10",
15
15
  "@types/yamljs": "0.2.31",
16
- "@typescript-eslint/eslint-plugin": "5.3.1",
17
- "@typescript-eslint/parser": "5.3.1",
18
- "eslint": "8.2.0",
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.4.1",
21
+ "prettier": "2.5.0",
22
22
  "ts-node": "10.4.0",
23
- "typescript": "4.4.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.14"
65
+ "version": "0.0.18"
63
66
  }