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
package/src/queryAble.ts CHANGED
@@ -1,66 +1,26 @@
1
1
  import { PgDbLogger } from "./pgDbLogger";
2
2
  import { pgUtils } from "./pgUtils";
3
3
  import * as stream from "stream";
4
+ import { IPgSchema } from "./pgSchemaInterface";
5
+ import * as pg from 'pg';
6
+ import util = require('util');
7
+ import QueryStream = require('pg-query-stream');
8
+ import through = require('through');
9
+ import {ResultFieldType, IPgDb} from "./pgDbInterface";
10
+ import {SqlQueryOptions, IQueryAble, PgRowResult } from "./queryAbleInterface"
4
11
 
5
- const util = require('util');
6
- const QueryStream = require('pg-query-stream');
7
- const through = require('through');
8
-
9
- export interface QueryOptions {
10
- limit?: number;
11
- offset?: number;
12
- orderBy?: string | string[] | { [fieldName: string]: 'asc' | 'desc' };//free text or column list
13
- groupBy?: string | string[];//free text or column list
14
- fields?: string | string[];//free text or column list
15
- logger?: PgDbLogger;
16
- forUpdate?: boolean;
17
- distinct?: boolean;
18
- skipUndefined?: boolean;
19
- }
20
-
21
- export interface SqlQueryOptions {
22
- logger?: PgDbLogger;
23
- }
24
-
25
- export interface ResultFieldType {
26
- name: string,
27
- tableID: number,
28
- columnID: number,
29
- dataTypeID: number,
30
- dataTypeSize: number,
31
- dataTypeModifier: number,
32
- format: string
33
- }
34
-
35
- export interface ResultType {
36
- command: 'SELECT' | 'UPDATE' | 'DELETE',
37
- rowCount: number,
38
- oid: number,
39
- rows: any[],
40
- fields: ResultFieldType[],
41
- _parsers: Function[][],
42
- RowCtor: Function[],
43
- rowsAsArray: boolean,
44
- _getTypeParser: Function[]
45
- }
46
-
47
- export interface PgRowResult {
48
- columns: string[],
49
- rows: any[]
50
- }
51
12
 
52
13
  let defaultLogger = {
53
14
  log: () => { },
54
15
  error: () => { }
55
16
  };
56
17
 
57
- export class QueryAble {
58
- db;
59
- schema;
60
- protected logger: PgDbLogger;
18
+ export abstract class QueryAble implements IQueryAble {
19
+ db!: IPgDb & IQueryAble; // assigned in async init
20
+ schema!: IPgSchema;
21
+ /*protected*/ logger!: PgDbLogger;
61
22
 
62
- constructor() {
63
- }
23
+ public static connectionErrorListener = () => { }
64
24
 
65
25
  setLogger(logger: PgDbLogger) {
66
26
  this.logger = logger;
@@ -84,15 +44,18 @@ export class QueryAble {
84
44
  * e.g. query('select * from a.b where id=$1;',['the_stage_is_set']);
85
45
  * e.g. query('select * from :!schema.:!table where id=:id;',{schema:'a',table:'b', id:'the_stage_is_set'});
86
46
  */
87
- async query(sql: string, params?: any[] | {}, options?: SqlQueryOptions): Promise<any[]> {
47
+ async query(sql: string, params?: any[] | {} | null, options?: SqlQueryOptions): Promise<any[]> {
88
48
  let connection = this.db.connection;
89
49
  let logger = (options && options.logger || this.getLogger(false));
90
50
  return this.internalQuery({ connection, sql, params, logger });
91
51
  }
92
52
 
93
- protected async internalQuery(options: { connection, sql: string, params?: any, logger?}): Promise<any[]>;
94
- protected async internalQuery(options: { connection, sql: string, params?: any, logger?, rowMode: true }): Promise<PgRowResult>;
95
- protected async internalQuery(options: { connection, sql: string, params?: any, logger?, rowMode?: boolean }): Promise<any[] | PgRowResult> {
53
+ protected async internalQuery(options: { connection: pg.PoolClient | null, sql: string, params?: any, logger?: PgDbLogger }): Promise<any[]>;
54
+ protected async internalQuery(options: { connection: pg.PoolClient | null, sql: string, params?: any, logger?: PgDbLogger, rowMode: true }): Promise<PgRowResult>;
55
+ protected async internalQuery(options: { connection: pg.PoolClient | null, sql: string, params?: any, logger?: PgDbLogger, rowMode?: boolean }): Promise<any[] | PgRowResult> {
56
+ if (this.db.needToFixConnectionForListen()) {
57
+ await this.db.runRestartConnectionForListen();
58
+ }
96
59
  let { connection, sql, params, logger } = options;
97
60
  logger = logger || this.getLogger(false);
98
61
 
@@ -102,40 +65,38 @@ export class QueryAble {
102
65
  sql = p.sql;
103
66
  params = p.params;
104
67
  }
105
-
68
+ let query = options?.rowMode ? { text: sql, values: params, rowMode: 'array' } : { text: sql, values: params };
69
+ let res;
106
70
  if (connection) {
107
71
  logger.log('reused connection', sql, util.inspect(params, false, null), connection.processID);
108
- let res = await connection.query({ text: sql, values: params, rowMode: options?.rowMode ? 'array' : undefined });
109
- pgUtils.postProcessResult(res.rows, res.fields, this.db.pgdbTypeParsers);
110
- if (this.db.postProcessResult) this.db.postProcessResult(res.rows, res.fields, logger);
111
-
112
- return options?.rowMode ? { columns: (res.fields || []).map(f => f.name), rows: res.rows || [] } : res.rows;
72
+ res = await connection.query(query);
73
+ await this.checkAndFixOids(connection, res.fields);
113
74
  } else {
114
75
  connection = await this.db.pool.connect();
115
76
  logger.log('new connection', sql, util.inspect(params, false, null), connection.processID);
116
77
 
78
+ connection.on('error', QueryAble.connectionErrorListener);
79
+ res = await connection.query(query);
80
+ await this.checkAndFixOids(connection, res.fields);
81
+
82
+ connection.off('error', QueryAble.connectionErrorListener);
83
+ connection.release();
84
+ connection = null;
85
+ }
86
+ this.postProcessFields(res.rows, res.fields, logger);
87
+ return options?.rowMode ? { columns: (res.fields || []).map(f => f.name), rows: res.rows || [] } : res.rows;
88
+ } catch (e) {
89
+ pgUtils.logError(logger, { error: <Error>e, sql, params, connection });
90
+ if (connection) {
117
91
  try {
118
- let res = await connection.query({ text: sql, values: params, rowMode: options?.rowMode ? 'array' : undefined });
92
+ //If any problem has happened in a dedicated connection, (wrong sql format or non-accessible postgres server)
93
+ //close the connection to be a free connection in the pool,
94
+ //but keep the db.connection member non - null to crash in all of the following commands
119
95
  connection.release();
120
- connection = null;
121
- pgUtils.postProcessResult(res.rows, res.fields, this.db.pgdbTypeParsers);
122
- if (this.db.postProcessResult) this.db.postProcessResult(res.rows, res.fields, logger);
123
-
124
- return options?.rowMode ? { columns: (res.fields || []).map(f => f.name), rows: res.rows || [] } : res.rows;
125
96
  } catch (e) {
126
- pgUtils.logError(logger, { error: e, sql, params, connection });
127
- try {
128
- if (connection)
129
- connection.release();
130
- } catch (e) {
131
- logger.error('connection error2', e.message);
132
- }
133
- connection = null;
134
- throw e;
97
+ logger.error('connection error', (<Error>e).message);
135
98
  }
136
99
  }
137
- } catch (e) {
138
- pgUtils.logError(logger, { error: e, sql, params, connection });
139
100
  throw e;
140
101
  }
141
102
  }
@@ -153,128 +114,191 @@ export class QueryAble {
153
114
  /**
154
115
  * If the callback function return true, the connection will be closed.
155
116
  */
156
- async queryWithOnCursorCallback(sql: string, params: any[] | {}, options: SqlQueryOptions, callback: (any) => any): Promise<void> {
157
- let connection = this.db.connection;
117
+ async queryWithOnCursorCallback(sql: string, params: any[] | Record<string, any> | null, options: SqlQueryOptions | null, callback: (res: any) => any): Promise<void> {
118
+ if (this.db.needToFixConnectionForListen()) {
119
+ await this.db.runRestartConnectionForListen();
120
+ }
121
+ let connection = this.db.connection!;
122
+ let logger = this.getLogger(true);
123
+ let positionedParams: any[] | null | undefined;
158
124
 
159
125
  try {
160
126
  if (params && !Array.isArray(params)) {
161
127
  let p = pgUtils.processNamedParams(sql, params);
162
128
  sql = p.sql;
163
129
  params = p.params;
130
+ } else {
131
+ positionedParams = params;
164
132
  }
165
133
 
166
- if (connection) {
167
- this.getLogger(false).log(sql, util.inspect(params, false, null), connection.processID);
168
- let query = new QueryStream(sql, params);
134
+ let queryInternal = async () => {
135
+ this.getLogger(false).log(sql, util.inspect(positionedParams, false, null), connection.processID);
136
+ let fieldsToFix: ResultFieldType[] | undefined;
137
+ let isFirst = true;
138
+
139
+ let query = new QueryStream(sql, positionedParams);
169
140
  let stream = connection.query(query);
170
141
  await new Promise((resolve, reject) => {
171
- stream.on('data', (res) => {
142
+ query.handleError = reject;
143
+ stream.on('data', (res: any) => {
172
144
  try {
173
145
  let fields = stream._result && stream._result.fields || stream.cursor._result && stream.cursor._result.fields;
174
- pgUtils.postProcessResult([res], fields, this.db.pgdbTypeParsers);
175
- if (this.db.postProcessResult) this.db.postProcessResult([res], fields, this.getLogger(false));
146
+ if (isFirst) {
147
+ if (this.hasUnknownOids(fields)) {
148
+ fieldsToFix = fields;
149
+ stream.destroy();
150
+ return;
151
+ }
152
+ isFirst = false;
153
+ }
154
+ this.postProcessFields([res], fields, this.getLogger(false));
176
155
 
177
156
  if (callback(res)) {
178
- stream.emit('close');
157
+ stream.destroy();
179
158
  }
180
159
  } catch (e) {
181
160
  reject(e);
182
161
  }
183
162
  });
184
163
 
185
- stream.on('end', resolve);
164
+ stream.on('close', resolve);
186
165
  stream.on('error', reject);
187
166
  });
188
-
189
- } else {
190
- try {
191
- connection = await this.db.pool.connect();
192
- this.getLogger(false).log(sql, util.inspect(params, false, null), connection.processID);
193
- let query = new QueryStream(sql, params);
194
- let stream = connection.query(query);
167
+ if (fieldsToFix) {
168
+ await this.checkAndFixOids(connection, fieldsToFix);
169
+ query = new QueryStream(sql, positionedParams);
170
+ stream = connection.query(query);
195
171
  await new Promise((resolve, reject) => {
196
- stream.on('data', (res) => {
172
+ query.handleError = reject;
173
+ stream.on('data', (res: any) => {
197
174
  try {
198
175
  let fields = stream._result && stream._result.fields || stream.cursor._result && stream.cursor._result.fields;
199
- pgUtils.postProcessResult([res], fields, this.db.pgdbTypeParsers);
200
- if (this.db.postProcessResult) this.db.postProcessResult([res], fields, this.getLogger(false));
176
+ this.postProcessFields([res], fields, this.getLogger(false));
201
177
 
202
178
  if (callback(res)) {
203
- stream.emit('close');
179
+ stream.destroy();
204
180
  }
205
181
  } catch (e) {
206
182
  reject(e);
207
183
  }
208
184
  });
209
185
 
210
- stream.on('end', resolve);
186
+ stream.on('close', resolve);
211
187
  stream.on('error', reject);
212
188
  });
213
- } finally {
214
- try {
215
- connection.release();
216
- } catch (e) {
217
- this.getLogger(true).error('connection error', e.message);
218
- }
219
189
  }
220
190
  }
191
+
192
+ if (connection) {
193
+ await queryInternal();
194
+ } else {
195
+ connection = await this.db.pool.connect();
196
+ logger.log('new connection', sql, util.inspect(positionedParams, false, null), connection.processID);
197
+ connection.on('error', QueryAble.connectionErrorListener);
198
+ await queryInternal();
199
+
200
+ connection.off('error', QueryAble.connectionErrorListener);
201
+ connection.release();
202
+ }
221
203
  } catch (e) {
222
- let logger = this.getLogger(true);
223
- pgUtils.logError(logger, { error: e, sql, params, connection });
204
+ pgUtils.logError(logger, { error: <Error>e, sql, params, connection });
205
+ if (connection) {
206
+ try {
207
+ connection.release();
208
+ } catch (e) {
209
+ logger.error('connection error', (<Error>e).message);
210
+ }
211
+ }
224
212
  throw e;
225
213
  }
226
214
  }
227
215
 
228
- async queryAsStream(sql: string, params?: any[] | {}, options?: SqlQueryOptions): Promise<stream.Readable> {
216
+ async queryAsStream(sql: string, params?: any[] | Record<string, any> | null, options?: SqlQueryOptions | null): Promise<stream.Readable> {
217
+ if (this.db.needToFixConnectionForListen()) {
218
+ await this.db.runRestartConnectionForListen();
219
+ }
229
220
  let connection = this.db.connection;
230
221
  let logger = (options && options.logger || this.getLogger(false));
231
- let pgStream;
232
- let pgdb = this.db;
233
- let convertTypeFilter = through(function (data) {
222
+ let pgStream: any;
223
+ let queriable = this;
224
+ let isFirst = true;
225
+ let convertTypeFilter = through(function (this: stream, data) {
234
226
  try {
235
227
  let fields = pgStream._result && pgStream._result.fields || pgStream.cursor._result && pgStream.cursor._result.fields;
236
- pgUtils.postProcessResult([data], fields, pgdb.pgdbTypeParsers);
237
- if (pgdb.postProcessResult) pgdb.postProcessResult([data], fields, logger);
228
+ if (isFirst) {
229
+ if (queriable.hasUnknownOids(fields)) {
230
+ throw new Error('[337] Query returns fields with unknown oid.');
231
+ }
232
+ isFirst = false;
233
+ }
234
+ queriable.postProcessFields([data], fields, queriable.db.pgdbTypeParsers);
238
235
 
239
236
  this.emit('data', data);
240
237
  } catch (err) {
241
238
  this.emit('error', err);
242
239
  }
243
240
  });
244
- convertTypeFilter.on('error', (e) => {
241
+ convertTypeFilter.on('error', (e: Error) => {
242
+ if (connection) {
243
+ try {
244
+ connection.release();
245
+ } catch (e) {
246
+ logger.error('connection error', (<Error>e).message);
247
+ }
248
+ }
249
+ connection = null;
245
250
  pgUtils.logError(logger, { error: e, sql, params, connection });
246
251
  });
247
252
 
253
+ let positionedParams: any[] | undefined | null;
254
+
248
255
  try {
249
256
  if (params && !Array.isArray(params)) {
250
257
  let p = pgUtils.processNamedParams(sql, params);
251
258
  sql = p.sql;
252
259
  params = p.params;
260
+ } else {
261
+ positionedParams = params;
253
262
  }
254
263
 
255
264
  if (connection) {
256
- logger.log(sql, util.inspect(params, false, null), connection.processID);
257
- let query = new QueryStream(sql, params);
265
+ logger.log(sql, util.inspect(positionedParams, false, null), connection.processID);
266
+ let query = new QueryStream(sql, positionedParams);
267
+ query.handleError = (err: Error) => {
268
+ convertTypeFilter.emit('error', err);
269
+ };
258
270
  pgStream = connection.query(query);
259
271
  return pgStream.pipe(convertTypeFilter);
260
272
  } else {
261
273
  connection = await this.db.pool.connect();
262
- logger.log(sql, util.inspect(params, false, null), connection.processID);
263
- let query = new QueryStream(sql, params);
274
+ logger.log('new connection', sql, util.inspect(positionedParams, false, null), connection.processID);
275
+ connection.on('error', QueryAble.connectionErrorListener);
276
+
277
+ let query = new QueryStream(sql, positionedParams);
278
+ query.handleError = (err: Error, _connection: pg.PoolClient) => {
279
+ convertTypeFilter.emit('error', err);
280
+ };
264
281
  pgStream = connection.query(query);
265
282
  pgStream.on('close', () => {
266
- if (connection) connection.release();
283
+ if (connection) {
284
+ connection.off('error', QueryAble.connectionErrorListener);
285
+ connection.release();
286
+ }
267
287
  connection = null;
268
288
  });
269
- pgStream.on('error', (e) => {
270
- pgUtils.logError(logger, { error: e, sql, params, connection });
271
- if (connection) connection.release();
289
+ pgStream.on('error', (e: Error) => {
290
+ pgUtils.logError(logger, { error: e, sql, params: positionedParams, connection });
291
+
292
+ if (connection) {
293
+ connection.off('error', QueryAble.connectionErrorListener);
294
+ connection.release();
295
+ }
272
296
  connection = null;
273
297
  });
274
298
  return pgStream.pipe(convertTypeFilter);
275
299
  }
276
300
  } catch (e) {
277
- pgUtils.logError(logger, { error: e, sql, params, connection });
301
+ pgUtils.logError(logger, { error: <Error>e, sql, params: positionedParams, connection });
278
302
  throw e;
279
303
  }
280
304
  }
@@ -320,4 +344,22 @@ export class QueryAble {
320
344
  let fieldName = Object.keys(res[0])[0];
321
345
  return res.map(r => r[fieldName]);
322
346
  }
347
+
348
+ private postProcessFields(rows: any[], fields: ResultFieldType[], logger: PgDbLogger) {
349
+ pgUtils.postProcessResult(rows, fields, this.db.pgdbTypeParsers);
350
+ if (this.db.postProcessResult) this.db.postProcessResult(rows, fields, logger);
351
+ }
352
+
353
+ private async checkAndFixOids(connection: pg.PoolClient, fields: ResultFieldType[]) {
354
+ if (fields) {
355
+ let oidList = fields.map(field => field.dataTypeID);
356
+ return this.db.resetMissingParsers(connection, oidList);
357
+ }
358
+ }
359
+
360
+ private hasUnknownOids(fields: ResultFieldType[]): boolean {
361
+ let oidList = fields.map(field => field.dataTypeID);
362
+ let unknownOids = oidList.filter(oid => !this.db.knownOids[oid]);
363
+ return !!unknownOids.length;
364
+ }
323
365
  }
@@ -0,0 +1,104 @@
1
+ import { PgDbLogger } from "./pgDbLogger";
2
+ import { IPgSchema } from "./pgSchemaInterface";
3
+ import * as stream from "stream";
4
+ import { ResultFieldType, IPgDb } from "./pgDbInterface";
5
+ import { ForceEscapeColumnsOptions } from "./connectionOptions";
6
+
7
+ export interface QueryOptions {
8
+ limit?: number;
9
+ offset?: number;
10
+ orderBy?: string | string[] | { [fieldName: string]: 'asc' | 'desc' };//free text or column list
11
+ /**
12
+ * only used with orderBy
13
+ * true -> nulls first,
14
+ * false -> nulls last
15
+ */
16
+ orderByNullsFirst?: boolean;
17
+ groupBy?: string | string[];//free text or column list
18
+ fields?: string | string[];//free text or column list
19
+ logger?: PgDbLogger;
20
+ forUpdate?: boolean;
21
+ distinct?: boolean;
22
+ skipUndefined?: boolean;
23
+ forceEscapeColumns?: boolean | ForceEscapeColumnsOptions
24
+ }
25
+
26
+ export interface SqlQueryOptions {
27
+ logger?: PgDbLogger;
28
+ }
29
+
30
+
31
+
32
+ export interface ResultType {
33
+ command: 'SELECT' | 'UPDATE' | 'DELETE',
34
+ rowCount: number,
35
+ oid: number,
36
+ rows: any[],
37
+ fields: ResultFieldType[],
38
+ _parsers: Function[][],
39
+ RowCtor: Function[],
40
+ rowsAsArray: boolean,
41
+ _getTypeParser: Function[]
42
+ }
43
+
44
+ export interface PgRowResult {
45
+ columns: string[],
46
+ rows: any[]
47
+ }
48
+
49
+ let defaultLogger = {
50
+ log: () => { },
51
+ error: () => { }
52
+ };
53
+
54
+
55
+
56
+ export interface IQueryAble {
57
+ db: IPgDb & IQueryAble; // assigned in async init
58
+ schema: IPgSchema;
59
+ logger: PgDbLogger;
60
+
61
+ /*connectionErrorListener : () => { }*/
62
+
63
+ setLogger(logger: PgDbLogger): void
64
+
65
+ getLogger(useConsoleAsDefault: boolean): PgDbLogger
66
+
67
+ /** alias to {@link query} */
68
+ run(sql: string, params?: any[] | {}, options?: SqlQueryOptions): Promise<any[]>
69
+
70
+ /**
71
+ * Params can be
72
+ * 1) array, then sql should have $1 $2 for placeholders
73
+ * 2) object, then sql should have:
74
+ * :example -> for params in statements (set/where), will be transformed to $1 $2 ...
75
+ * :!example -> for DDL names (schema, table, column), will be replaced in the query
76
+ * e.g. query('select * from a.b where id=$1;',['the_stage_is_set']);
77
+ * e.g. query('select * from :!schema.:!table where id=:id;',{schema:'a',table:'b', id:'the_stage_is_set'});
78
+ */
79
+ query(sql: string, params?: any[] | {} | null, options?: SqlQueryOptions): Promise<any[]>
80
+
81
+ /**
82
+ * Same as query but response is two array: columns and rows and rows are arrays also not objects
83
+ * This is useful for queries which have colliding column names
84
+ */
85
+ queryAsRows(sql: string, params?: any[] | {}, options?: SqlQueryOptions): Promise<PgRowResult>
86
+
87
+ /**
88
+ * If the callback function return true, the connection will be closed.
89
+ */
90
+ queryWithOnCursorCallback(sql: string, params: any[] | Record<string, any> | null, options: SqlQueryOptions | null, callback: (res: any) => any): Promise<void>
91
+
92
+ queryAsStream(sql: string, params?: any[] | Record<string, any> | null, options?: SqlQueryOptions | null): Promise<stream.Readable>
93
+
94
+ queryOne(sql: string, params?: any[] | {}, options?: SqlQueryOptions): Promise<any>
95
+
96
+ queryFirst(sql: string, params?: any[] | {}, options?: SqlQueryOptions): Promise<any>
97
+
98
+ /** @return one record's one field */
99
+ queryOneField(sql: string, params?: any[] | {}, options?: SqlQueryOptions): Promise<any>
100
+
101
+ /** @return one column for the matching records */
102
+ queryOneColumn(sql: string, params?: any[] | {}, options?: SqlQueryOptions): Promise<any[]>
103
+
104
+ }