pogi 2.10.2 → 3.0.0-beta2

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.
Files changed (83) hide show
  1. package/.vscode/launch.json +47 -15
  2. package/CHANGELOG.md +11 -0
  3. package/docs/API/PgDb.md +25 -0
  4. package/docs/notification.md +19 -0
  5. package/jest.config.js +23 -0
  6. package/lib/bin/generateInterface.js +3 -3
  7. package/lib/bin/generateInterface.js.map +1 -1
  8. package/lib/connectionOptions.d.ts +10 -0
  9. package/lib/index.d.ts +1 -1
  10. package/lib/pgConverters.d.ts +9 -8
  11. package/lib/pgConverters.js +46 -32
  12. package/lib/pgConverters.js.map +1 -1
  13. package/lib/pgConverters.test.d.ts +1 -0
  14. package/lib/pgConverters.test.js +13 -0
  15. package/lib/pgConverters.test.js.map +1 -0
  16. package/lib/pgDb.d.ts +27 -27
  17. package/lib/pgDb.js +293 -100
  18. package/lib/pgDb.js.map +1 -1
  19. package/lib/pgDb.test.d.ts +1 -0
  20. package/lib/pgDb.test.js +1126 -0
  21. package/lib/pgDb.test.js.map +1 -0
  22. package/lib/pgDbInterface.d.ts +53 -0
  23. package/lib/pgDbInterface.js +11 -0
  24. package/lib/pgDbInterface.js.map +1 -0
  25. package/lib/pgDbOperators.d.ts +3 -3
  26. package/lib/pgDbOperators.js +4 -7
  27. package/lib/pgDbOperators.js.map +1 -1
  28. package/lib/pgDbOperators.test.d.ts +1 -0
  29. package/lib/pgDbOperators.test.js +313 -0
  30. package/lib/pgDbOperators.test.js.map +1 -0
  31. package/lib/pgSchema.d.ts +10 -9
  32. package/lib/pgSchema.js.map +1 -1
  33. package/lib/pgSchemaInterface.d.ts +12 -0
  34. package/lib/pgSchemaInterface.js +3 -0
  35. package/lib/pgSchemaInterface.js.map +1 -0
  36. package/lib/pgTable.d.ts +15 -40
  37. package/lib/pgTable.js +54 -54
  38. package/lib/pgTable.js.map +1 -1
  39. package/lib/pgTableInterface.d.ts +102 -0
  40. package/lib/pgTableInterface.js +4 -0
  41. package/lib/pgTableInterface.js.map +1 -0
  42. package/lib/pgUtils.d.ts +16 -6
  43. package/lib/pgUtils.js +162 -31
  44. package/lib/pgUtils.js.map +1 -1
  45. package/lib/queryAble.d.ts +20 -53
  46. package/lib/queryAble.js +149 -80
  47. package/lib/queryAble.js.map +1 -1
  48. package/lib/queryAbleInterface.d.ts +55 -0
  49. package/lib/queryAbleInterface.js +7 -0
  50. package/lib/queryAbleInterface.js.map +1 -0
  51. package/lib/queryWhere.d.ts +2 -2
  52. package/lib/queryWhere.js +19 -23
  53. package/lib/queryWhere.js.map +1 -1
  54. package/mkdocs.yml +1 -0
  55. package/package.json +21 -11
  56. package/src/bin/generateInterface.ts +2 -2
  57. package/src/connectionOptions.ts +48 -13
  58. package/src/index.d.ts +7 -0
  59. package/src/index.ts +1 -1
  60. package/src/pgConverters.test.ts +10 -0
  61. package/src/pgConverters.ts +34 -22
  62. package/src/pgDb.test.ts +1324 -0
  63. package/src/pgDb.ts +318 -122
  64. package/src/pgDbInterface.ts +57 -0
  65. package/src/pgDbOperators.test.ts +478 -0
  66. package/src/pgDbOperators.ts +45 -22
  67. package/src/pgSchema.ts +10 -9
  68. package/src/pgSchemaInterface.ts +12 -0
  69. package/src/pgTable.ts +66 -98
  70. package/src/pgTableInterface.ts +131 -0
  71. package/src/pgUtils.ts +166 -42
  72. package/src/queryAble.ts +167 -125
  73. package/src/queryAbleInterface.ts +104 -0
  74. package/src/queryWhere.ts +42 -43
  75. package/{spec/resources → src/test}/init.sql +23 -0
  76. package/src/test/pgServiceRestartTest.ts +1500 -0
  77. package/{spec/resources → src/test}/throw_exception.sql +0 -0
  78. package/{spec/resources → src/test}/tricky.sql +0 -0
  79. package/{src/tsconfig.json → tsconfig.json} +12 -11
  80. package/spec/run.js +0 -5
  81. package/spec/support/jasmine.json +0 -9
  82. package/src/test/pgDbOperatorSpec.ts +0 -492
  83. package/src/test/pgDbSpec.ts +0 -994
@@ -0,0 +1,12 @@
1
+ import { IPgDb } from "./pgDbInterface";
2
+ import { IPgTable } from "./pgTableInterface";
3
+ import { IQueryAble } from "./queryAbleInterface";
4
+
5
+ export interface IPgSchema extends IQueryAble {
6
+ schemaName: string;
7
+
8
+ tables: { [name: string]: IPgTable<any> };
9
+ fn: { [name: string]: (...args: any[]) => any };
10
+ [name: string]: any | IPgTable<any>;
11
+
12
+ }
package/src/pgTable.ts CHANGED
@@ -1,60 +1,28 @@
1
- import {QueryAble, QueryOptions} from "./queryAble";
2
- import {PgDb, FieldType} from "./pgDb";
3
- import {PgDbLogger} from "./pgDbLogger"
4
- import generateWhere from "./queryWhere";
5
- import {PgSchema} from "./pgSchema";
6
- import {pgUtils} from "./pgUtils";
7
1
  import * as _ from 'lodash';
8
2
  import * as stream from "stream";
3
+ import { FieldType } from "./pgDb";
4
+ import { IPgDb } from "./pgDbInterface";
5
+ import { PgSchema } from "./pgSchema";
6
+ import { CountOption, InsertOption, IPgTable, Return, Stream, TruncateOptions, UpdateDeleteOption, UpsertOption } from "./pgTableInterface";
7
+ import { pgUtils } from "./pgUtils";
8
+ import { QueryAble } from "./queryAble";
9
+ import { QueryOptions } from "./queryAbleInterface";
10
+ import generateWhere from "./queryWhere";
9
11
 
10
- const util = require('util');
11
-
12
- export interface InsertOption {
13
- logger?: PgDbLogger;
14
- }
15
-
16
- export interface Return {
17
- return?: string[] | '*';
18
- }
19
-
20
- export interface UpdateDeleteOption {
21
- skipUndefined?: boolean;
22
- logger?: PgDbLogger;
23
- }
24
-
25
- export interface UpsertOption {
26
- constraint?: string,
27
- columns?: string[],
28
- logger?: PgDbLogger;
29
- }
30
-
31
- export interface CountOption {
32
- skipUndefined?: boolean;
33
- logger?: PgDbLogger;
34
- }
35
-
36
- export interface Stream {
37
- stream: true;
38
- }
39
-
40
- export interface TruncateOptions {
41
- restartIdentity?: boolean,
42
- cascade?: boolean,
43
- logger?: PgDbLogger;
44
- }
45
12
 
46
- export class PgTable<T> extends QueryAble {
13
+ export class PgTable<T> extends QueryAble implements IPgTable<T> {
47
14
  qualifiedName: string;
48
15
  pkey: string;
49
- db: PgDb;
16
+ db: IPgDb;
50
17
  fieldTypes: { [index: string]: FieldType }; //written directly
51
18
 
52
- constructor(public schema: PgSchema, protected desc: { name: string, pkey?:string, schema: string }, fieldTypes = {}) {
19
+ constructor(public schema: PgSchema, protected desc: { name: string, pkey?: string, schema: string }, fieldTypes: Record<string, FieldType> = {}) {
53
20
  super();
54
21
  this.db = schema.db;
55
- this.qualifiedName = util.format('"%s"."%s"', desc.schema, desc.name);
22
+ this.qualifiedName = `${pgUtils.quoteFieldName(desc.schema)}.${pgUtils.quoteFieldName(desc.name)}`;
56
23
  this.pkey = desc.pkey || desc.name + "_pkey"; //poor man's pkey (could be queried by why?)
57
24
  this.fieldTypes = fieldTypes;
25
+ return this
58
26
  }
59
27
 
60
28
  toString() {
@@ -89,9 +57,9 @@ export class PgTable<T> extends QueryAble {
89
57
  return 0; // just return empty arrays so bulk inserting variable-length lists is more friendly
90
58
  }
91
59
 
92
- let {sql, parameters} = this.getInsertQuery(records);
60
+ let { sql, parameters } = this.getInsertQuery(records);
93
61
  sql = "WITH __RESULT as ( " + sql + " RETURNING 1) SELECT SUM(1) FROM __RESULT";
94
- let result = await this.query(sql, parameters, {logger: options.logger});
62
+ let result = await this.query(sql, parameters, { logger: options.logger });
95
63
  return result[0].sum;
96
64
  }
97
65
 
@@ -110,11 +78,11 @@ export class PgTable<T> extends QueryAble {
110
78
  return []; // just return empty arrays so bulk inserting variable-length lists is more friendly
111
79
  }
112
80
 
113
- let {sql, parameters} = this.getInsertQuery(records);
81
+ let { sql, parameters } = this.getInsertQuery(records);
114
82
 
115
- sql += " RETURNING " + (options && options.return && Array.isArray(options.return) ? options.return.map(pgUtils.quoteField).join(',') : '*');
83
+ sql += " RETURNING " + (options && options.return && Array.isArray(options.return) ? options.return.map(pgUtils.quoteFieldName).join(',') : '*');
116
84
 
117
- let result = await this.query(sql, parameters, {logger: options.logger});
85
+ let result = await this.query(sql, parameters, { logger: options.logger });
118
86
  if (options.return && options.return.length == 0) {
119
87
  return new Array(returnSingle ? 1 : records.length).fill({});
120
88
  }
@@ -142,15 +110,15 @@ export class PgTable<T> extends QueryAble {
142
110
  }
143
111
 
144
112
  async update(conditions: { [k: string]: any }, fields: { [k: string]: any }, options?: UpdateDeleteOption): Promise<number> {
145
- let {sql, parameters} = this.getUpdateQuery(conditions, fields, options);
113
+ let { sql, parameters } = this.getUpdateQuery(conditions, fields, options);
146
114
  sql = "WITH __RESULT as ( " + sql + " RETURNING 1) SELECT SUM(1) FROM __RESULT";
147
115
  let res = await this.query(sql, parameters, options);
148
116
  return res[0].sum;
149
117
  };
150
118
 
151
119
  async updateAndGet(conditions: { [k: string]: any }, fields: { [k: string]: any }, options?: UpdateDeleteOption & Return): Promise<T[]> {
152
- let {sql, parameters} = this.getUpdateQuery(conditions, fields, options);
153
- sql += " RETURNING " + (options && options.return && Array.isArray(options.return) ? options.return.map(pgUtils.quoteField).join(',') : '*');
120
+ let { sql, parameters } = this.getUpdateQuery(conditions, fields, options);
121
+ sql += " RETURNING " + (options && options.return && Array.isArray(options.return) ? options.return.map(pgUtils.quoteFieldName).join(',') : '*');
154
122
  return this.query(sql, parameters, options);
155
123
  };
156
124
 
@@ -163,9 +131,9 @@ export class PgTable<T> extends QueryAble {
163
131
  throw new Error("insert should be called with data");
164
132
  }
165
133
 
166
- let {sql, parameters} = this.getUpsertQuery(record, options);
134
+ let { sql, parameters } = this.getUpsertQuery(record, options);
167
135
  sql = "WITH __RESULT as ( " + sql + " RETURNING 1) SELECT SUM(1) FROM __RESULT";
168
- let result = await this.query(sql, parameters, {logger: options.logger});
136
+ let result = await this.query(sql, parameters, { logger: options.logger });
169
137
  return result[0].sum;
170
138
  };
171
139
 
@@ -178,19 +146,19 @@ export class PgTable<T> extends QueryAble {
178
146
  throw new Error("insert should be called with data");
179
147
  }
180
148
 
181
- let {sql, parameters} = this.getUpsertQuery(record, options);
182
- sql += " RETURNING " + (options && options.return && Array.isArray(options.return) ? options.return.map(pgUtils.quoteField).join(',') : '*');
149
+ let { sql, parameters } = this.getUpsertQuery(record, options);
150
+ sql += " RETURNING " + (options && options.return && Array.isArray(options.return) ? options.return.map(pgUtils.quoteFieldName).join(',') : '*');
183
151
 
184
- let result = await this.query(sql, parameters, {logger: options.logger});
152
+ let result = await this.query(sql, parameters, { logger: options.logger });
185
153
 
186
154
  if (options.return && options.return.length == 0) {
187
155
  return <T>{};
188
156
  }
189
157
  return result[0];
190
- };
158
+ };
191
159
 
192
160
  async delete(conditions: { [k: string]: any }, options?: UpdateDeleteOption): Promise<number> {
193
- let {sql, parameters} = this.getDeleteQuery(conditions, options);
161
+ let { sql, parameters } = this.getDeleteQuery(conditions, options);
194
162
  sql = "WITH __RESULT as ( " + sql + " RETURNING 1) SELECT SUM(1) FROM __RESULT";
195
163
  let res = await this.query(sql, parameters, options);
196
164
  return res[0].sum;
@@ -206,8 +174,8 @@ export class PgTable<T> extends QueryAble {
206
174
 
207
175
  async deleteAndGet(conditions: { [k: string]: any }, options?: UpdateDeleteOption & Return): Promise<any[]> {
208
176
  options = options || {};
209
- let {sql, parameters} = this.getDeleteQuery(conditions, options);
210
- sql += " RETURNING " + (options && options.return && Array.isArray(options.return) ? options.return.map(pgUtils.quoteField).join(',') : '*');
177
+ let { sql, parameters } = this.getDeleteQuery(conditions, options);
178
+ sql += " RETURNING " + (options && options.return && Array.isArray(options.return) ? options.return.map(pgUtils.quoteFieldName).join(',') : '*');
211
179
  return this.query(sql, parameters);
212
180
  }
213
181
 
@@ -234,19 +202,19 @@ export class PgTable<T> extends QueryAble {
234
202
  if (options && options.cascade) {
235
203
  sql += ' CASCADE';
236
204
  }
237
- await this.query(sql, null, options);
205
+ await this.query(sql, undefined, options);
238
206
  }
239
207
 
240
208
  async find(conditions: { [k: string]: any }, options?: QueryOptions): Promise<T[]>
241
209
  async find(conditions: { [k: string]: any }, options?: QueryOptions & Stream): Promise<stream.Readable>
242
210
  async find(conditions: { [k: string]: any }, options?: any): Promise<any> {
243
211
  options = options || {};
244
- options.skipUndefined = options.skipUndefined === true || (options.skipUndefined === undefined && ['all', 'select'].indexOf(this.db.config.skipUndefined) > -1);
212
+ options.skipUndefined = options.skipUndefined === true || (options.skipUndefined === undefined && this.db.config.skipUndefined && ['all', 'select'].includes(this.db.config.skipUndefined));
245
213
  let where = _.isEmpty(conditions) ? {
246
- where: " ",
247
- params: null
214
+ where: "",
215
+ params: undefined
248
216
  } : generateWhere(conditions, this.fieldTypes, this.qualifiedName, 0, options.skipUndefined);
249
- let sql = `SELECT ${pgUtils.processQueryFields(options)} FROM ${this.qualifiedName} ${where.where} ${pgUtils.processQueryOptions(options)}`;
217
+ let sql = `SELECT ${pgUtils.processQueryFields(options)} FROM ${this.qualifiedName} ${where.where} ${pgUtils.processQueryOptions<T>(options, this)}`;
250
218
  return options.stream ? this.queryAsStream(sql, where.params, options) : this.query(sql, where.params, options);
251
219
  }
252
220
 
@@ -255,7 +223,7 @@ export class PgTable<T> extends QueryAble {
255
223
  async findWhere(where: string, params: any[] | {}, options?: QueryOptions & Stream): Promise<stream.Readable>
256
224
  async findWhere(where: string, params: any, options?: any): Promise<any> {
257
225
  options = options || {};
258
- let sql = `SELECT ${pgUtils.processQueryFields(options)} FROM ${this.qualifiedName} WHERE ${where} ${pgUtils.processQueryOptions(options)}`;
226
+ let sql = `SELECT ${pgUtils.processQueryFields(options)} FROM ${this.qualifiedName} WHERE ${where} ${pgUtils.processQueryOptions<T>(options, this)}`;
259
227
  return options.stream ? this.queryAsStream(sql, params, options) : this.query(sql, params, options);
260
228
  }
261
229
 
@@ -263,22 +231,22 @@ export class PgTable<T> extends QueryAble {
263
231
  public async findAll(options?: QueryOptions & Stream): Promise<stream.Readable>
264
232
  public async findAll(options?: any): Promise<any> {
265
233
  options = options || {};
266
- let sql = `SELECT ${pgUtils.processQueryFields(options)} FROM ${this.qualifiedName} ${pgUtils.processQueryOptions(options)}`;
267
- return options.stream ? this.queryAsStream(sql, null, options) : this.query(sql, null, options);
234
+ let sql = `SELECT ${pgUtils.processQueryFields(options)} FROM ${this.qualifiedName} ${pgUtils.processQueryOptions<T>(options, this)}`;
235
+ return options.stream ? this.queryAsStream(sql, undefined, options) : this.query(sql, null, options);
268
236
  }
269
237
 
270
- async findOne(conditions, options?: QueryOptions): Promise<T> {
238
+ async findOne(conditions: Record<string, any>, options?: QueryOptions): Promise<T> {
271
239
  let res = await this.find(conditions, options);
272
240
  if (res.length > 1) {
273
241
  let logger = (options && options.logger || this.getLogger(false));
274
242
  let error = new Error('More then one rows exists');
275
- pgUtils.logError(logger, { error, sql:this.qualifiedName, params: conditions, connection: this.db.connection });
243
+ pgUtils.logError(logger, { error, sql: this.qualifiedName, params: conditions, connection: this.db.connection });
276
244
  throw error;
277
245
  }
278
246
  return res[0];
279
247
  }
280
248
 
281
- async findFirst(conditions, options?: QueryOptions): Promise<T> {
249
+ async findFirst(conditions: Record<string, any>, options?: QueryOptions): Promise<T> {
282
250
  options = options || {};
283
251
  options.limit = 1;
284
252
  let res = await this.find(conditions, options);
@@ -286,19 +254,19 @@ export class PgTable<T> extends QueryAble {
286
254
  }
287
255
 
288
256
 
289
- async count(conditions?: {}, options?: CountOption): Promise<number> {
257
+ async count(conditions?: Record<string, any>, options?: CountOption): Promise<number> {
290
258
  options = options || {};
291
- options.skipUndefined = options.skipUndefined === true || (options.skipUndefined === undefined && ['all', 'select'].indexOf(this.db.config.skipUndefined) > -1);
259
+ options.skipUndefined = options.skipUndefined === true || (options.skipUndefined === undefined && this.db.config.skipUndefined && ['all', 'select'].includes(this.db.config.skipUndefined));
292
260
 
293
261
  let where = _.isEmpty(conditions) ? {
294
262
  where: " ",
295
- params: null
296
- } : generateWhere(conditions, this.fieldTypes, this.qualifiedName, 0, options.skipUndefined);
263
+ params: undefined
264
+ } : generateWhere(conditions!, this.fieldTypes, this.qualifiedName, 0, options.skipUndefined);
297
265
  let sql = `SELECT COUNT(*) c FROM ${this.qualifiedName} ${where.where}`;
298
266
  return (await this.queryOneField(sql, where.params));
299
267
  }
300
268
 
301
- async findOneFieldOnly(conditions, field: string, options?: QueryOptions): Promise<any> {
269
+ async findOneFieldOnly(conditions: Record<string, any>, field: string, options?: QueryOptions): Promise<any> {
302
270
  options = options || {};
303
271
  options.fields = [field];
304
272
  let res = await this.findOne(conditions, options);
@@ -314,33 +282,33 @@ export class PgTable<T> extends QueryAble {
314
282
  }
315
283
  });
316
284
  let columns = Object.keys(columnsMap);
317
- let sql = util.format("INSERT INTO %s (%s) VALUES\n", this.qualifiedName, columns.map(pgUtils.quoteField).join(", "));
318
- let parameters = [];
285
+ let sql = `INSERT INTO ${this.qualifiedName} (${columns.map(pgUtils.quoteFieldName).join(", ")}) VALUES\n`;
286
+ let parameters: string[] = [];
319
287
  let placeholders = [];
320
288
 
321
289
  for (let i = 0, seed = 0; i < records.length; i++) {
322
290
  placeholders.push('(' + columns.map(c => "$" + (++seed)).join(', ') + ')');
323
- parameters.push.apply(parameters, columns.map(c => pgUtils.transformInsertUpdateParams(records[i][c], this.fieldTypes[c])));
291
+ parameters.push(...columns.map(c => pgUtils.transformInsertUpdateParams(records[i][c], this.fieldTypes[c])));
324
292
  }
325
293
  sql += placeholders.join(",\n");
326
294
 
327
- return {sql, parameters};
295
+ return { sql, parameters };
328
296
 
329
297
  }
330
298
 
331
- protected getUpdateSetSnipplet(fields: { [k: string]: any }, parameters?:any[] ): { snipplet: string, parameters: any[] } {
299
+ protected getUpdateSetSnippet(fields: { [k: string]: any }, parameters?: any[]): { snippet: string, parameters: any[] } {
332
300
  let params = parameters || [];
333
- let f = [];
301
+ let f: string[] = [];
334
302
  let seed = params.length;
335
303
 
336
304
  _.each(fields, (value, fieldName) => {
337
305
  if (value === undefined) return;
338
306
 
339
- f.push(util.format('%s = $%s', pgUtils.quoteField(fieldName), (++seed)));
307
+ f.push(`${pgUtils.quoteFieldName(fieldName)} = $${(++seed)}`);
340
308
  params.push(pgUtils.transformInsertUpdateParams(value, this.fieldTypes[fieldName]));
341
309
  });
342
310
 
343
- return {snipplet: f.join(', '), parameters: params};
311
+ return { snippet: f.join(', '), parameters: params };
344
312
  }
345
313
 
346
314
  protected getUpdateQuery(conditions: { [k: string]: any }, fields: { [k: string]: any }, options?: UpdateDeleteOption): { sql: string, parameters: any[] } {
@@ -353,49 +321,49 @@ export class PgTable<T> extends QueryAble {
353
321
  throw new Error('Missing fields for update');
354
322
  }
355
323
 
356
- let {snipplet, parameters} = this.getUpdateSetSnipplet(fields);
357
- let sql = util.format("UPDATE %s SET %s", this.qualifiedName, snipplet);
324
+ let { snippet, parameters } = this.getUpdateSetSnippet(fields);
325
+ let sql = `UPDATE ${this.qualifiedName} SET ${snippet}`;
358
326
 
359
327
  if (!hasConditions || !_.isEmpty(conditions)) {
360
328
  let parsedWhere = generateWhere(conditions, this.fieldTypes, this.qualifiedName, parameters.length, options.skipUndefined);
361
329
  sql += parsedWhere.where;
362
330
  parameters = parameters.concat(parsedWhere.params);
363
331
  }
364
- return {sql, parameters};
332
+ return { sql, parameters };
365
333
  }
366
334
 
367
335
  protected getUpsertQuery(record: T, options?: UpsertOption): { sql: string, parameters: any[] } {
368
336
  options = options || {};
369
-
337
+
370
338
  if (_.isEmpty(record)) {
371
339
  throw new Error('Missing fields for upsert');
372
340
  }
373
341
 
374
342
  let insert = this.getInsertQuery([record]);
375
- let {snipplet, parameters} = this.getUpdateSetSnipplet(record, insert.parameters);
343
+ let { snippet, parameters } = this.getUpdateSetSnippet(record, insert.parameters);
376
344
  let sql = insert.sql;
377
345
 
378
346
  if (options.columns) {
379
- sql += " ON CONFLICT (" + options.columns.map(c=>pgUtils.quoteField(c)).join(', ') + ") DO UPDATE SET " + snipplet;
347
+ sql += ` ON CONFLICT (${options.columns.map(c => pgUtils.quoteFieldName(c)).join(', ')}) DO UPDATE SET ${snippet}`;
380
348
  } else {
381
- let constraint = options.constraint || this.pkey;
382
- sql += " ON CONFLICT ON CONSTRAINT " + util.format('"%s"', constraint) + " DO UPDATE SET " + snipplet;
349
+ let constraint = pgUtils.quoteFieldName(options.constraint || this.pkey);
350
+ sql += ` ON CONFLICT ON CONSTRAINT ${constraint} DO UPDATE SET ${snippet}`;
383
351
  }
384
-
385
- return {sql, parameters};
352
+
353
+ return { sql, parameters };
386
354
  }
387
355
 
388
356
  protected getDeleteQuery(conditions: { [k: string]: any }, options?: UpdateDeleteOption): { sql: string, parameters: any[] } {
389
357
  options = options || {};
390
358
  options.skipUndefined = options.skipUndefined === true || (options.skipUndefined === undefined && this.db.config.skipUndefined === 'all');
391
359
 
392
- let sql = util.format("DELETE FROM %s ", this.qualifiedName);
360
+ let sql = `DELETE FROM ${this.qualifiedName} `;
393
361
 
394
362
  let parsedWhere;
395
363
  if (!_.isEmpty(conditions)) {
396
364
  parsedWhere = generateWhere(conditions, this.fieldTypes, this.qualifiedName, 0, options.skipUndefined);
397
365
  sql += parsedWhere.where;
398
366
  }
399
- return {sql, parameters: parsedWhere && parsedWhere.params || []}
367
+ return { sql, parameters: parsedWhere && parsedWhere.params || [] }
400
368
  }
401
369
  }
@@ -0,0 +1,131 @@
1
+ import { IQueryAble, QueryOptions } from "./queryAbleInterface";
2
+ import { PgDb, FieldType } from "./pgDb";
3
+ import { IPgDb } from "./pgDbInterface";
4
+ import { IPgSchema } from "./pgSchemaInterface";
5
+ import { PgDbLogger } from "./pgDbLogger"
6
+ import * as _ from 'lodash';
7
+ import * as stream from "stream";
8
+
9
+ const util = require('util');
10
+
11
+ export interface InsertOption {
12
+ logger?: PgDbLogger;
13
+ }
14
+
15
+ export interface Return {
16
+ return?: string[] | '*';
17
+ }
18
+
19
+ export interface UpdateDeleteOption {
20
+ skipUndefined?: boolean;
21
+ logger?: PgDbLogger;
22
+ }
23
+
24
+ export interface UpsertOption {
25
+ constraint?: string,
26
+ columns?: string[],
27
+ logger?: PgDbLogger;
28
+ }
29
+
30
+ export interface CountOption {
31
+ skipUndefined?: boolean;
32
+ logger?: PgDbLogger;
33
+ }
34
+
35
+ export interface Stream {
36
+ stream: true;
37
+ }
38
+
39
+ export interface TruncateOptions {
40
+ restartIdentity?: boolean,
41
+ cascade?: boolean,
42
+ logger?: PgDbLogger;
43
+ }
44
+
45
+ export interface IPgTable<T> extends IQueryAble {
46
+ qualifiedName: string;
47
+ pkey: string;
48
+ db: IPgDb;
49
+ fieldTypes: { [index: string]: FieldType }; //written directly
50
+
51
+ toString: () => String
52
+
53
+ /**
54
+ * If you dont want to use the result set the options.return to false
55
+ * by default it is true. Also can set it to the fields that need to be returned,
56
+ * e.g.:
57
+ *
58
+ * let res = await table.insert([{username:'anonymous'},{username:'anonymous2'}], {return:['id']})
59
+ * res; // [{id:1},{id:2}]
60
+ *
61
+ * let res = await table.insert({username:'anonymous'}, {return:false})
62
+ * res; // void
63
+ *
64
+ * let res = await table.insert({username:'anonymous'})
65
+ * res; // {id:1, name:'anonymous', created:'...'}
66
+ *
67
+ */
68
+ insert(records: T[], options?: InsertOption): Promise<number>
69
+ insert(records: T, options?: InsertOption): Promise<number>
70
+ insert(records: any, options?: any): Promise<any>
71
+
72
+ insertAndGet(records: T[], options?: InsertOption & Return): Promise<T[]>
73
+ insertAndGet(records: T, options?: InsertOption & Return): Promise<T>
74
+ insertAndGet(records: any, options?: InsertOption & Return): Promise<any>
75
+
76
+ updateOne(conditions: { [k: string]: any }, fields: { [k: string]: any }, options?: UpdateDeleteOption): Promise<number>
77
+
78
+ updateAndGetOne(conditions: { [k: string]: any }, fields: { [k: string]: any }, options?: UpdateDeleteOption & Return): Promise<T>
79
+
80
+ update(conditions: { [k: string]: any }, fields: { [k: string]: any }, options?: UpdateDeleteOption): Promise<number>
81
+
82
+ updateAndGet(conditions: { [k: string]: any }, fields: { [k: string]: any }, options?: UpdateDeleteOption & Return): Promise<T[]>
83
+
84
+ /**
85
+ * columnsOrConstraintName is by default the primary key
86
+ */
87
+ upsert(record: T, options?: UpsertOption): Promise<number>
88
+
89
+ /**
90
+ * columnsOrConstraintName is by default the primary key
91
+ */
92
+ upsertAndGet(record: T, options?: UpsertOption & Return): Promise<T>
93
+
94
+ delete(conditions: { [k: string]: any }, options?: UpdateDeleteOption): Promise<number>
95
+
96
+ deleteOne(conditions: { [k: string]: any }, options?: UpdateDeleteOption): Promise<number>
97
+
98
+ deleteAndGet(conditions: { [k: string]: any }, options?: UpdateDeleteOption & Return): Promise<any[]>
99
+
100
+ deleteAndGetOne(conditions: { [k: string]: any }, options?: UpdateDeleteOption & Return): Promise<any>
101
+
102
+ // async deleteAll(options?:UpdateDeleteOption):Promise<number> {
103
+ // let sql = util.format("DELETE FROM %s ", this.qualifiedName);
104
+ // sql = "WITH __RESULT as ( " + sql + " RETURNING 1) SELECT SUM(1) FROM __RESULT";
105
+ // let res = await this.query(sql, {logger:options.logger});
106
+ // return res[0].sum;
107
+ // }
108
+
109
+ truncate(options?: TruncateOptions): Promise<void>
110
+
111
+ find(conditions: { [k: string]: any }, options?: QueryOptions): Promise<T[]>
112
+ find(conditions: { [k: string]: any }, options?: QueryOptions & Stream): Promise<stream.Readable>
113
+ find(conditions: { [k: string]: any }, options?: any): Promise<any>
114
+
115
+ findWhere(where: string, params: any[] | {}, options?: QueryOptions): Promise<T[]>
116
+ findWhere(where: string, params: any[] | {}, options?: QueryOptions & Stream): Promise<stream.Readable>
117
+ findWhere(where: string, params: any, options?: any): Promise<any>
118
+
119
+ findAll(options?: QueryOptions): Promise<T[]>
120
+ findAll(options?: QueryOptions & Stream): Promise<stream.Readable>
121
+ findAll(options?: any): Promise<any>
122
+
123
+ findOne(conditions: Record<string, any>, options?: QueryOptions): Promise<T>
124
+
125
+ findFirst(conditions: Record<string, any>, options?: QueryOptions): Promise<T>
126
+
127
+ count(conditions?: {}, options?: CountOption): Promise<number>
128
+
129
+ findOneFieldOnly(conditions: Record<string, any>, field: string, options?: QueryOptions): Promise<any>
130
+
131
+ }