postgrejs 2.12.0

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 (215) hide show
  1. package/CHANGELOG.md +814 -0
  2. package/LICENSE +21 -0
  3. package/README.md +200 -0
  4. package/cjs/connection/bind-param.js +10 -0
  5. package/cjs/connection/connection.js +279 -0
  6. package/cjs/connection/cursor.js +93 -0
  7. package/cjs/connection/intl-connection.js +243 -0
  8. package/cjs/connection/pool.js +226 -0
  9. package/cjs/connection/portal.js +148 -0
  10. package/cjs/connection/prepared-statement.js +217 -0
  11. package/cjs/constants.js +250 -0
  12. package/cjs/data-type-map.js +119 -0
  13. package/cjs/data-types/bool-type.js +27 -0
  14. package/cjs/data-types/box-type.js +52 -0
  15. package/cjs/data-types/bytea-type.js +29 -0
  16. package/cjs/data-types/char-type.js +27 -0
  17. package/cjs/data-types/circle-type.js +48 -0
  18. package/cjs/data-types/date-type.js +67 -0
  19. package/cjs/data-types/float4-type.js +25 -0
  20. package/cjs/data-types/float8-type.js +25 -0
  21. package/cjs/data-types/int2-type.js +26 -0
  22. package/cjs/data-types/int2-vector-type.js +38 -0
  23. package/cjs/data-types/int4-type.js +26 -0
  24. package/cjs/data-types/int8-type.js +31 -0
  25. package/cjs/data-types/json-type.js +38 -0
  26. package/cjs/data-types/jsonb-type.js +42 -0
  27. package/cjs/data-types/lseg-type.js +52 -0
  28. package/cjs/data-types/numeric-type.js +125 -0
  29. package/cjs/data-types/oid-type.js +32 -0
  30. package/cjs/data-types/point-type.js +39 -0
  31. package/cjs/data-types/time-type.js +54 -0
  32. package/cjs/data-types/timestamp-type.js +81 -0
  33. package/cjs/data-types/timestamptz-type.js +73 -0
  34. package/cjs/data-types/uuid-type.js +39 -0
  35. package/cjs/data-types/varchar-type.js +27 -0
  36. package/cjs/index.js +41 -0
  37. package/cjs/interfaces/command-result.js +2 -0
  38. package/cjs/interfaces/data-mapping-options.js +2 -0
  39. package/cjs/interfaces/data-type.js +2 -0
  40. package/cjs/interfaces/database-connection-params.js +2 -0
  41. package/cjs/interfaces/field-info.js +2 -0
  42. package/cjs/interfaces/query-options.js +2 -0
  43. package/cjs/interfaces/query-result.js +2 -0
  44. package/cjs/interfaces/script-execute-options.js +2 -0
  45. package/cjs/interfaces/script-result.js +2 -0
  46. package/cjs/interfaces/statement-prepare-options.js +2 -0
  47. package/cjs/package.json +3 -0
  48. package/cjs/protocol/backend.js +256 -0
  49. package/cjs/protocol/buffer-reader.js +78 -0
  50. package/cjs/protocol/database-error.js +17 -0
  51. package/cjs/protocol/frontend.js +218 -0
  52. package/cjs/protocol/pg-socket.js +345 -0
  53. package/cjs/protocol/protocol.js +71 -0
  54. package/cjs/protocol/sasl.js +108 -0
  55. package/cjs/protocol/smart-buffer.js +195 -0
  56. package/cjs/safe-event-emitter.js +17 -0
  57. package/cjs/types.js +2 -0
  58. package/cjs/util/array-calculatedim.js +19 -0
  59. package/cjs/util/bigint-methods.js +42 -0
  60. package/cjs/util/config-from-env.js +30 -0
  61. package/cjs/util/connection-config.js +65 -0
  62. package/cjs/util/convert-row-to-object.js +13 -0
  63. package/cjs/util/decode-binaryarray.js +39 -0
  64. package/cjs/util/encode-binaryarray.js +45 -0
  65. package/cjs/util/escape-literal.js +27 -0
  66. package/cjs/util/fast-parseint.js +32 -0
  67. package/cjs/util/get-parsers.js +42 -0
  68. package/cjs/util/parse-array.js +61 -0
  69. package/cjs/util/parse-datetime.js +38 -0
  70. package/cjs/util/parse-row.js +11 -0
  71. package/cjs/util/parse-time.js +29 -0
  72. package/cjs/util/stringify-arrayliteral.js +38 -0
  73. package/cjs/util/stringify-for-sql.js +30 -0
  74. package/cjs/util/wrap-row-description.js +35 -0
  75. package/esm/connection/bind-param.js +6 -0
  76. package/esm/connection/connection.js +275 -0
  77. package/esm/connection/cursor.js +86 -0
  78. package/esm/connection/intl-connection.js +238 -0
  79. package/esm/connection/pool.js +222 -0
  80. package/esm/connection/portal.js +144 -0
  81. package/esm/connection/prepared-statement.js +213 -0
  82. package/esm/constants.js +247 -0
  83. package/esm/data-type-map.js +115 -0
  84. package/esm/data-types/bool-type.js +24 -0
  85. package/esm/data-types/box-type.js +49 -0
  86. package/esm/data-types/bytea-type.js +23 -0
  87. package/esm/data-types/char-type.js +24 -0
  88. package/esm/data-types/circle-type.js +45 -0
  89. package/esm/data-types/date-type.js +64 -0
  90. package/esm/data-types/float4-type.js +22 -0
  91. package/esm/data-types/float8-type.js +22 -0
  92. package/esm/data-types/int2-type.js +23 -0
  93. package/esm/data-types/int2-vector-type.js +35 -0
  94. package/esm/data-types/int4-type.js +23 -0
  95. package/esm/data-types/int8-type.js +28 -0
  96. package/esm/data-types/json-type.js +35 -0
  97. package/esm/data-types/jsonb-type.js +39 -0
  98. package/esm/data-types/lseg-type.js +49 -0
  99. package/esm/data-types/numeric-type.js +121 -0
  100. package/esm/data-types/oid-type.js +29 -0
  101. package/esm/data-types/point-type.js +36 -0
  102. package/esm/data-types/time-type.js +51 -0
  103. package/esm/data-types/timestamp-type.js +78 -0
  104. package/esm/data-types/timestamptz-type.js +70 -0
  105. package/esm/data-types/uuid-type.js +36 -0
  106. package/esm/data-types/varchar-type.js +24 -0
  107. package/esm/index.js +25 -0
  108. package/esm/interfaces/command-result.js +1 -0
  109. package/esm/interfaces/data-mapping-options.js +1 -0
  110. package/esm/interfaces/data-type.js +1 -0
  111. package/esm/interfaces/database-connection-params.js +1 -0
  112. package/esm/interfaces/field-info.js +1 -0
  113. package/esm/interfaces/query-options.js +1 -0
  114. package/esm/interfaces/query-result.js +1 -0
  115. package/esm/interfaces/script-execute-options.js +1 -0
  116. package/esm/interfaces/script-result.js +1 -0
  117. package/esm/interfaces/statement-prepare-options.js +1 -0
  118. package/esm/protocol/backend.js +252 -0
  119. package/esm/protocol/buffer-reader.js +74 -0
  120. package/esm/protocol/database-error.js +13 -0
  121. package/esm/protocol/frontend.js +214 -0
  122. package/esm/protocol/pg-socket.js +338 -0
  123. package/esm/protocol/protocol.js +68 -0
  124. package/esm/protocol/sasl.js +102 -0
  125. package/esm/protocol/smart-buffer.js +168 -0
  126. package/esm/safe-event-emitter.js +13 -0
  127. package/esm/types.js +1 -0
  128. package/esm/util/array-calculatedim.js +15 -0
  129. package/esm/util/bigint-methods.js +37 -0
  130. package/esm/util/config-from-env.js +26 -0
  131. package/esm/util/connection-config.js +57 -0
  132. package/esm/util/convert-row-to-object.js +9 -0
  133. package/esm/util/decode-binaryarray.js +35 -0
  134. package/esm/util/encode-binaryarray.js +41 -0
  135. package/esm/util/escape-literal.js +23 -0
  136. package/esm/util/fast-parseint.js +28 -0
  137. package/esm/util/get-parsers.js +38 -0
  138. package/esm/util/parse-array.js +57 -0
  139. package/esm/util/parse-datetime.js +34 -0
  140. package/esm/util/parse-row.js +7 -0
  141. package/esm/util/parse-time.js +25 -0
  142. package/esm/util/stringify-arrayliteral.js +34 -0
  143. package/esm/util/stringify-for-sql.js +25 -0
  144. package/esm/util/wrap-row-description.js +31 -0
  145. package/package.json +54 -0
  146. package/typings/connection/bind-param.d.ts +6 -0
  147. package/typings/connection/connection.d.ts +110 -0
  148. package/typings/connection/cursor.d.ts +25 -0
  149. package/typings/connection/intl-connection.d.ts +40 -0
  150. package/typings/connection/pool.d.ts +52 -0
  151. package/typings/connection/portal.d.ts +23 -0
  152. package/typings/connection/prepared-statement.d.ts +27 -0
  153. package/typings/constants.d.ts +130 -0
  154. package/typings/data-type-map.d.ts +11 -0
  155. package/typings/data-types/bool-type.d.ts +3 -0
  156. package/typings/data-types/box-type.d.ts +3 -0
  157. package/typings/data-types/bytea-type.d.ts +3 -0
  158. package/typings/data-types/char-type.d.ts +3 -0
  159. package/typings/data-types/circle-type.d.ts +3 -0
  160. package/typings/data-types/date-type.d.ts +3 -0
  161. package/typings/data-types/float4-type.d.ts +3 -0
  162. package/typings/data-types/float8-type.d.ts +3 -0
  163. package/typings/data-types/int2-type.d.ts +3 -0
  164. package/typings/data-types/int2-vector-type.d.ts +3 -0
  165. package/typings/data-types/int4-type.d.ts +3 -0
  166. package/typings/data-types/int8-type.d.ts +3 -0
  167. package/typings/data-types/json-type.d.ts +3 -0
  168. package/typings/data-types/jsonb-type.d.ts +3 -0
  169. package/typings/data-types/lseg-type.d.ts +3 -0
  170. package/typings/data-types/numeric-type.d.ts +12 -0
  171. package/typings/data-types/oid-type.d.ts +4 -0
  172. package/typings/data-types/point-type.d.ts +3 -0
  173. package/typings/data-types/time-type.d.ts +3 -0
  174. package/typings/data-types/timestamp-type.d.ts +3 -0
  175. package/typings/data-types/timestamptz-type.d.ts +3 -0
  176. package/typings/data-types/uuid-type.d.ts +3 -0
  177. package/typings/data-types/varchar-type.d.ts +3 -0
  178. package/typings/index.d.ts +25 -0
  179. package/typings/interfaces/command-result.d.ts +28 -0
  180. package/typings/interfaces/data-mapping-options.d.ts +9 -0
  181. package/typings/interfaces/data-type.d.ts +31 -0
  182. package/typings/interfaces/database-connection-params.d.ts +38 -0
  183. package/typings/interfaces/field-info.d.ts +46 -0
  184. package/typings/interfaces/query-options.d.ts +46 -0
  185. package/typings/interfaces/query-result.d.ts +8 -0
  186. package/typings/interfaces/script-execute-options.d.ts +26 -0
  187. package/typings/interfaces/script-result.d.ts +15 -0
  188. package/typings/interfaces/statement-prepare-options.d.ts +13 -0
  189. package/typings/protocol/backend.d.ts +9 -0
  190. package/typings/protocol/buffer-reader.d.ts +18 -0
  191. package/typings/protocol/database-error.d.ts +20 -0
  192. package/typings/protocol/frontend.d.ts +59 -0
  193. package/typings/protocol/pg-socket.d.ts +51 -0
  194. package/typings/protocol/protocol.d.ts +180 -0
  195. package/typings/protocol/sasl.d.ts +13 -0
  196. package/typings/protocol/smart-buffer.d.ts +39 -0
  197. package/typings/safe-event-emitter.d.ts +5 -0
  198. package/typings/types.d.ts +15 -0
  199. package/typings/util/array-calculatedim.d.ts +1 -0
  200. package/typings/util/bigint-methods.d.ts +3 -0
  201. package/typings/util/config-from-env.d.ts +2 -0
  202. package/typings/util/connection-config.d.ts +3 -0
  203. package/typings/util/convert-row-to-object.d.ts +2 -0
  204. package/typings/util/decode-binaryarray.d.ts +4 -0
  205. package/typings/util/encode-binaryarray.d.ts +5 -0
  206. package/typings/util/escape-literal.d.ts +1 -0
  207. package/typings/util/fast-parseint.d.ts +1 -0
  208. package/typings/util/get-parsers.d.ts +4 -0
  209. package/typings/util/parse-array.d.ts +5 -0
  210. package/typings/util/parse-datetime.d.ts +1 -0
  211. package/typings/util/parse-row.d.ts +3 -0
  212. package/typings/util/parse-time.d.ts +3 -0
  213. package/typings/util/stringify-arrayliteral.d.ts +3 -0
  214. package/typings/util/stringify-for-sql.d.ts +4 -0
  215. package/typings/util/wrap-row-description.d.ts +5 -0
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getIntlConnection = exports.IntlConnection = void 0;
4
+ const power_tasks_1 = require("power-tasks");
5
+ const putil_varhelpers_1 = require("putil-varhelpers");
6
+ const constants_js_1 = require("../constants.js");
7
+ const data_type_map_js_1 = require("../data-type-map.js");
8
+ const pg_socket_js_1 = require("../protocol/pg-socket.js");
9
+ const protocol_js_1 = require("../protocol/protocol.js");
10
+ const safe_event_emitter_js_1 = require("../safe-event-emitter.js");
11
+ const connection_config_js_1 = require("../util/connection-config.js");
12
+ const convert_row_to_object_js_1 = require("../util/convert-row-to-object.js");
13
+ const escape_literal_js_1 = require("../util/escape-literal.js");
14
+ const get_parsers_js_1 = require("../util/get-parsers.js");
15
+ const parse_row_js_1 = require("../util/parse-row.js");
16
+ const wrap_row_description_js_1 = require("../util/wrap-row-description.js");
17
+ const DataFormat = protocol_js_1.Protocol.DataFormat;
18
+ class IntlConnection extends safe_event_emitter_js_1.SafeEventEmitter {
19
+ constructor(config) {
20
+ super();
21
+ this._refCount = 0;
22
+ this.transactionStatus = 'I';
23
+ this.statementQueue = new power_tasks_1.TaskQueue({ concurrency: 1 });
24
+ this._config = Object.freeze((0, connection_config_js_1.getConnectionConfig)(config));
25
+ this.socket = new pg_socket_js_1.PgSocket(this._config);
26
+ this.socket.on('error', err => this._onError(err));
27
+ this.socket.on('close', () => this.emit('close'));
28
+ this.socket.on('notification', payload => this.emit('notification', payload));
29
+ this.socket.on('connecting', () => this.emit('connecting'));
30
+ this._onErrorSavePoint = 'SP_' + Math.round(Math.random() * 100000000);
31
+ }
32
+ get config() {
33
+ return this._config;
34
+ }
35
+ get inTransaction() {
36
+ return this.transactionStatus === 'T' || this.transactionStatus === 'E';
37
+ }
38
+ get state() {
39
+ return this.socket.state;
40
+ }
41
+ get refCount() {
42
+ return this._refCount;
43
+ }
44
+ get processID() {
45
+ return this.socket.processID;
46
+ }
47
+ get secretKey() {
48
+ return this.socket.secretKey;
49
+ }
50
+ get sessionParameters() {
51
+ return this.socket.sessionParameters;
52
+ }
53
+ async connect() {
54
+ if (this.socket.state === constants_js_1.ConnectionState.READY)
55
+ return;
56
+ await new Promise((resolve, reject) => {
57
+ const handleConnectError = err => reject(err);
58
+ this.socket.once('ready', () => {
59
+ this.socket.removeListener('error', handleConnectError);
60
+ resolve();
61
+ });
62
+ this.socket.once('error', handleConnectError);
63
+ this.socket.connect();
64
+ });
65
+ let startupCommand = '';
66
+ if (this.config.schema)
67
+ startupCommand += 'SET search_path = ' + (0, escape_literal_js_1.escapeLiteral)(this.config.schema) + ';';
68
+ if (this.config.timezone)
69
+ startupCommand += 'SET timezone TO ' + (0, escape_literal_js_1.escapeLiteral)(this.config.timezone) + ';';
70
+ if (startupCommand)
71
+ await this.execute(startupCommand, { autoCommit: true });
72
+ this.emit('ready');
73
+ }
74
+ async close() {
75
+ if (this.state === constants_js_1.ConnectionState.CLOSED)
76
+ return;
77
+ this.statementQueue.clearQueue();
78
+ return new Promise(resolve => {
79
+ if (this.socket.state === constants_js_1.ConnectionState.CLOSED)
80
+ return;
81
+ this.socket.once('close', resolve);
82
+ this.socket.sendTerminateMessage(() => {
83
+ this.socket.close();
84
+ this.emit('close');
85
+ });
86
+ });
87
+ }
88
+ async execute(sql, options, cb) {
89
+ this.assertConnected();
90
+ return this.statementQueue
91
+ .enqueue(async () => {
92
+ const transactionCommand = sql.match(/^(\bBEGIN\b|\bCOMMIT\b|\bSTART\b|\bROLLBACK|SAVEPOINT|RELEASE\b)/i);
93
+ let beginFirst = false;
94
+ let commitLast = false;
95
+ if (!transactionCommand) {
96
+ if (!this.inTransaction &&
97
+ (options?.autoCommit != null ? options?.autoCommit : this.config.autoCommit) === false) {
98
+ beginFirst = true;
99
+ }
100
+ if (this.inTransaction && options?.autoCommit)
101
+ commitLast = true;
102
+ }
103
+ if (beginFirst)
104
+ await this._execute('BEGIN');
105
+ const rollbackOnError = !transactionCommand &&
106
+ (options?.rollbackOnError != null
107
+ ? options.rollbackOnError
108
+ : (0, putil_varhelpers_1.coerceToBoolean)(this.config.rollbackOnError, true));
109
+ if (this.inTransaction && rollbackOnError)
110
+ await this._execute('SAVEPOINT ' + this._onErrorSavePoint);
111
+ try {
112
+ const result = await this._execute(sql, options, cb);
113
+ if (commitLast)
114
+ await this._execute('COMMIT');
115
+ else if (this.inTransaction && rollbackOnError)
116
+ await this._execute('RELEASE ' + this._onErrorSavePoint + ';');
117
+ return result;
118
+ }
119
+ catch (e) {
120
+ if (this.inTransaction && rollbackOnError)
121
+ await this._execute('ROLLBACK TO ' + this._onErrorSavePoint + ';');
122
+ throw e;
123
+ }
124
+ })
125
+ .toPromise();
126
+ }
127
+ async startTransaction() {
128
+ if (!this.inTransaction)
129
+ await this.execute('BEGIN');
130
+ }
131
+ async savepoint(name) {
132
+ if (!(name && name.match(/^[a-zA-Z]\w+$/)))
133
+ throw new Error(`Invalid savepoint "${name}`);
134
+ await this.execute('BEGIN; SAVEPOINT ' + name);
135
+ }
136
+ async commit() {
137
+ if (this.inTransaction)
138
+ await this.execute('COMMIT');
139
+ }
140
+ async rollback() {
141
+ if (this.inTransaction)
142
+ await this.execute('ROLLBACK');
143
+ }
144
+ async rollbackToSavepoint(name) {
145
+ if (!(name && name.match(/^[a-zA-Z]\w+$/)))
146
+ throw new Error(`Invalid savepoint "${name}`);
147
+ await this.execute('ROLLBACK TO SAVEPOINT ' + name, { autoCommit: false });
148
+ }
149
+ async releaseSavepoint(name) {
150
+ if (!(name && name.match(/^[a-zA-Z]\w+$/)))
151
+ throw new Error(`Invalid savepoint "${name}`);
152
+ await this.execute('RELEASE SAVEPOINT ' + name, { autoCommit: false });
153
+ }
154
+ ref() {
155
+ this._refCount++;
156
+ }
157
+ unref() {
158
+ this._refCount--;
159
+ return !this._refCount;
160
+ }
161
+ assertConnected() {
162
+ if (this.state === constants_js_1.ConnectionState.CLOSING)
163
+ throw new Error('Connection is closing');
164
+ if (this.state === constants_js_1.ConnectionState.CLOSED)
165
+ throw new Error('Connection closed');
166
+ }
167
+ async _execute(sql, options, cb) {
168
+ this.ref();
169
+ try {
170
+ const startTime = Date.now();
171
+ const result = {
172
+ totalCommands: 0,
173
+ totalTime: 0,
174
+ results: [],
175
+ };
176
+ const opts = options || {};
177
+ this.socket.sendQueryMessage(sql);
178
+ let currentStart = Date.now();
179
+ let parsers;
180
+ let current = { command: undefined };
181
+ let fields;
182
+ const typeMap = opts.typeMap || data_type_map_js_1.GlobalTypeMap;
183
+ return await this.socket.capture(async (code, msg, done) => {
184
+ switch (code) {
185
+ case protocol_js_1.Protocol.BackendMessageCode.NoticeResponse:
186
+ case protocol_js_1.Protocol.BackendMessageCode.CopyInResponse:
187
+ case protocol_js_1.Protocol.BackendMessageCode.CopyOutResponse:
188
+ case protocol_js_1.Protocol.BackendMessageCode.EmptyQueryResponse:
189
+ break;
190
+ case protocol_js_1.Protocol.BackendMessageCode.RowDescription:
191
+ fields = msg.fields;
192
+ parsers = (0, get_parsers_js_1.getParsers)(typeMap, fields);
193
+ current.fields = (0, wrap_row_description_js_1.wrapRowDescription)(typeMap, fields, DataFormat.text);
194
+ current.rows = [];
195
+ break;
196
+ case protocol_js_1.Protocol.BackendMessageCode.DataRow:
197
+ let row = msg.columns.map((x) => x.toString('utf8'));
198
+ (0, parse_row_js_1.parseRow)(parsers, row, opts);
199
+ if (opts.objectRows && current.fields)
200
+ row = (0, convert_row_to_object_js_1.convertRowToObject)(current.fields, row);
201
+ if (cb)
202
+ cb('row', row);
203
+ current.rows = current.rows || [];
204
+ current.rows.push(row);
205
+ break;
206
+ case protocol_js_1.Protocol.BackendMessageCode.CommandComplete:
207
+ // Ignore BEGIN command that we added to sql
208
+ current.command = msg.command;
209
+ if (current.command === 'DELETE' || current.command === 'INSERT' || current.command === 'UPDATE')
210
+ current.rowsAffected = msg.rowCount;
211
+ current.executeTime = Date.now() - currentStart;
212
+ if (current.rows)
213
+ current.rowType = opts.objectRows && current.fields ? 'object' : 'array';
214
+ result.results.push(current);
215
+ if (cb)
216
+ cb('command-complete', current);
217
+ current = { command: undefined };
218
+ currentStart = Date.now();
219
+ break;
220
+ case protocol_js_1.Protocol.BackendMessageCode.ReadyForQuery:
221
+ this.transactionStatus = msg.status;
222
+ result.totalTime = Date.now() - startTime;
223
+ // Ignore COMMIT command that we added to sql
224
+ result.totalCommands = result.results.length;
225
+ done(undefined, result);
226
+ }
227
+ });
228
+ }
229
+ finally {
230
+ this.unref();
231
+ }
232
+ }
233
+ _onError(err) {
234
+ if (this.socket.state !== constants_js_1.ConnectionState.READY)
235
+ return;
236
+ this.emit('error', err);
237
+ }
238
+ }
239
+ exports.IntlConnection = IntlConnection;
240
+ function getIntlConnection(connection) {
241
+ return connection._intlCon;
242
+ }
243
+ exports.getIntlConnection = getIntlConnection;
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Pool = void 0;
4
+ const lightning_pool_1 = require("lightning-pool");
5
+ const putil_varhelpers_1 = require("putil-varhelpers");
6
+ const constants_js_1 = require("../constants.js");
7
+ const safe_event_emitter_js_1 = require("../safe-event-emitter.js");
8
+ const connection_config_js_1 = require("../util/connection-config.js");
9
+ const connection_js_1 = require("./connection.js");
10
+ const intl_connection_js_1 = require("./intl-connection.js");
11
+ class Pool extends safe_event_emitter_js_1.SafeEventEmitter {
12
+ constructor(config) {
13
+ super();
14
+ this._notificationListeners = new safe_event_emitter_js_1.SafeEventEmitter();
15
+ const cfg = (0, connection_config_js_1.getConnectionConfig)(config);
16
+ this.config = Object.freeze(cfg);
17
+ const poolOptions = {};
18
+ poolOptions.acquireMaxRetries = (0, putil_varhelpers_1.coerceToInt)(cfg.acquireMaxRetries, 0);
19
+ poolOptions.acquireRetryWait = (0, putil_varhelpers_1.coerceToInt)(cfg.acquireRetryWait, 2000);
20
+ poolOptions.acquireTimeoutMillis = (0, putil_varhelpers_1.coerceToInt)(cfg.acquireTimeoutMillis, 0);
21
+ poolOptions.idleTimeoutMillis = (0, putil_varhelpers_1.coerceToInt)(cfg.idleTimeoutMillis, 30000);
22
+ poolOptions.max = (0, putil_varhelpers_1.coerceToInt)(cfg.max, 10);
23
+ poolOptions.maxQueue = (0, putil_varhelpers_1.coerceToInt)(cfg.maxQueue, 1000);
24
+ poolOptions.max = (0, putil_varhelpers_1.coerceToInt)(cfg.max, 10);
25
+ poolOptions.min = (0, putil_varhelpers_1.coerceToInt)(cfg.min, 0);
26
+ poolOptions.minIdle = (0, putil_varhelpers_1.coerceToInt)(cfg.minIdle, 0);
27
+ poolOptions.validation = (0, putil_varhelpers_1.coerceToBoolean)(cfg.validation, false);
28
+ const poolFactory = {
29
+ create: async () => {
30
+ /* istanbul ignore next */
31
+ if (this.listenerCount('debug'))
32
+ this.emit('debug', {
33
+ location: 'Pool.factory.create',
34
+ pool: this,
35
+ message: `new connection creating`,
36
+ });
37
+ const intlCon = new intl_connection_js_1.IntlConnection(cfg);
38
+ await intlCon.connect();
39
+ intlCon.on('close', () => this._pool.destroy(intlCon));
40
+ /* istanbul ignore next */
41
+ if (this.listenerCount('debug'))
42
+ this.emit('debug', {
43
+ location: 'Pool.factory.create',
44
+ pool: this,
45
+ message: `[${intlCon.processID}] connection created`,
46
+ });
47
+ return intlCon;
48
+ },
49
+ destroy: intlCon => {
50
+ /* istanbul ignore next */
51
+ if (this.listenerCount('debug'))
52
+ this.emit('debug', {
53
+ location: 'Pool.factory.destroy',
54
+ pool: this,
55
+ message: `[${intlCon.processID}] connection destroy`,
56
+ });
57
+ return intlCon.close();
58
+ },
59
+ reset: async (intlCon) => {
60
+ /* istanbul ignore next */
61
+ if (this.listenerCount('debug'))
62
+ this.emit('debug', {
63
+ location: 'Pool.factory.reset',
64
+ pool: this,
65
+ message: `[${intlCon.processID}] connection reset`,
66
+ });
67
+ try {
68
+ if (intlCon.state === constants_js_1.ConnectionState.READY) {
69
+ await intlCon.execute('ROLLBACK;UNLISTEN *');
70
+ }
71
+ }
72
+ finally {
73
+ intlCon.removeAllListeners();
74
+ intlCon.once('close', () => this._pool.destroy(intlCon));
75
+ intlCon._refCount = 0;
76
+ }
77
+ },
78
+ validate: async (intlCon) => {
79
+ /* istanbul ignore next */
80
+ if (this.listenerCount('debug'))
81
+ this.emit('debug', {
82
+ location: 'Pool.factory.validate',
83
+ pool: this,
84
+ message: `[${intlCon.processID}] connection validate`,
85
+ });
86
+ if (intlCon.state !== constants_js_1.ConnectionState.READY)
87
+ throw new Error('Connection is not active');
88
+ await intlCon.execute('select 1;');
89
+ },
90
+ };
91
+ this._pool = new lightning_pool_1.Pool(poolFactory, poolOptions);
92
+ this._pool.on('return', (...args) => this.emit('release', ...args));
93
+ this._pool.on('error', (...args) => this.emit('error', ...args));
94
+ this._pool.on('acquire', (...args) => this.emit('acquire', ...args));
95
+ this._pool.on('destroy', (...args) => this.emit('destroy', ...args));
96
+ this._pool.start();
97
+ }
98
+ /**
99
+ * Returns number of connections that are currently acquired
100
+ */
101
+ get acquiredConnections() {
102
+ return this._pool.acquired;
103
+ }
104
+ /**
105
+ * Returns number of unused connections in the pool
106
+ */
107
+ get idleConnections() {
108
+ return this._pool.available;
109
+ }
110
+ /**
111
+ * Returns total number of connections in the pool regardless of whether they are idle or in use
112
+ */
113
+ get totalConnections() {
114
+ return this._pool.size;
115
+ }
116
+ /**
117
+ * Obtains a connection from the connection pool
118
+ */
119
+ async acquire() {
120
+ const intlCon = await this._pool.acquire();
121
+ /* istanbul ignore next */
122
+ if (this.listenerCount('debug'))
123
+ this.emit('debug', {
124
+ location: 'Pool.acquire',
125
+ pool: this,
126
+ message: `[${intlCon.processID}] acquired`,
127
+ });
128
+ const connection = new connection_js_1.Connection(this, intlCon);
129
+ /* istanbul ignore next */
130
+ if (this.listenerCount('debug'))
131
+ connection.on('debug', (...args) => this.emit('debug', ...args));
132
+ return connection;
133
+ }
134
+ /**
135
+ * Shuts down the pool and destroys all resources.
136
+ */
137
+ async close(terminateWait) {
138
+ this._notificationListeners.removeAllListeners();
139
+ await this._notificationConnection?.close(terminateWait);
140
+ const ms = terminateWait == null ? 10000 : terminateWait;
141
+ return this._pool.closeAsync(ms);
142
+ }
143
+ /**
144
+ * Executes a script
145
+ */
146
+ async execute(sql, options) {
147
+ const connection = await this.acquire();
148
+ try {
149
+ return await connection.execute(sql, options);
150
+ }
151
+ finally {
152
+ await this.release(connection);
153
+ }
154
+ }
155
+ /**
156
+ * Executes a query
157
+ */
158
+ async query(sql, options) {
159
+ const connection = await this.acquire();
160
+ try {
161
+ return await connection.query(sql, options);
162
+ }
163
+ finally {
164
+ await this.release(connection);
165
+ }
166
+ }
167
+ async prepare(sql, options) {
168
+ const connection = await this.acquire();
169
+ const statement = await connection.prepare(sql, options);
170
+ statement.once('close', () => this._pool.release((0, intl_connection_js_1.getIntlConnection)(connection)));
171
+ return statement;
172
+ }
173
+ release(connection) {
174
+ return this._pool.releaseAsync((0, intl_connection_js_1.getIntlConnection)(connection));
175
+ }
176
+ async listen(channel, callback) {
177
+ if (!/^[A-Z]\w+$/i.test(channel))
178
+ throw new TypeError(`Invalid channel name`);
179
+ this._notificationListeners.on(channel, callback);
180
+ await this._initNotificationConnection();
181
+ }
182
+ async unListen(channel) {
183
+ if (!/^[A-Z]\w+$/i.test(channel))
184
+ throw new TypeError(`Invalid channel name`);
185
+ this._notificationListeners.removeAllListeners(channel);
186
+ if (!this._notificationListeners.eventNames().length) {
187
+ await this.unListenAll();
188
+ }
189
+ else if (this._notificationConnection)
190
+ await this._notificationConnection.unListen(channel);
191
+ }
192
+ async unListenAll() {
193
+ this._notificationListeners.removeAllListeners();
194
+ if (this._notificationConnection) {
195
+ const conn = this._notificationConnection;
196
+ this._notificationConnection = undefined;
197
+ await conn.close();
198
+ }
199
+ }
200
+ async _initNotificationConnection() {
201
+ if (this._notificationConnection)
202
+ return;
203
+ const conn = (this._notificationConnection = new connection_js_1.Connection(this.config));
204
+ // Reconnect on connection lost
205
+ conn.on('close', () => reConnect());
206
+ const registerEvents = async () => {
207
+ const channels = this._notificationListeners.eventNames();
208
+ for (const channel of channels) {
209
+ const fns = this._notificationListeners.listeners(channel);
210
+ for (const fn of fns) {
211
+ await conn.listen(channel, fn);
212
+ }
213
+ }
214
+ };
215
+ const reConnect = async () => {
216
+ setTimeout(() => {
217
+ if (!this._notificationListeners.eventNames().length)
218
+ return;
219
+ conn.connect().catch(() => reConnect());
220
+ }, 500).unref();
221
+ };
222
+ await conn.connect();
223
+ await registerEvents();
224
+ }
225
+ }
226
+ exports.Pool = Pool;
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Portal = void 0;
4
+ const constants_js_1 = require("../constants.js");
5
+ const data_type_map_js_1 = require("../data-type-map.js");
6
+ const protocol_js_1 = require("../protocol/protocol.js");
7
+ const intl_connection_js_1 = require("./intl-connection.js");
8
+ class Portal {
9
+ constructor(statement, name) {
10
+ this._columnFormat = constants_js_1.DEFAULT_COLUMN_FORMAT;
11
+ this._statement = statement;
12
+ this._name = name;
13
+ }
14
+ get connection() {
15
+ return this._statement.connection;
16
+ }
17
+ get name() {
18
+ return this._name;
19
+ }
20
+ async bind(params, queryOptions) {
21
+ const intoCon = (0, intl_connection_js_1.getIntlConnection)(this.connection);
22
+ intoCon.ref();
23
+ try {
24
+ const socket = intoCon.socket;
25
+ this._columnFormat = queryOptions.columnFormat != null ? queryOptions.columnFormat : protocol_js_1.Protocol.DataFormat.binary;
26
+ socket.sendBindMessage({
27
+ typeMap: queryOptions.typeMap || data_type_map_js_1.GlobalTypeMap,
28
+ statement: this._statement.name,
29
+ portal: this.name,
30
+ paramTypes: this._statement.paramTypes,
31
+ params,
32
+ queryOptions,
33
+ });
34
+ socket.sendFlushMessage();
35
+ return await socket.capture(async (code, msg, done) => {
36
+ switch (code) {
37
+ case protocol_js_1.Protocol.BackendMessageCode.BindComplete:
38
+ done();
39
+ break;
40
+ case protocol_js_1.Protocol.BackendMessageCode.NoticeResponse:
41
+ break;
42
+ default:
43
+ done(new Error(`Server returned unexpected response message (${String.fromCharCode(code)})`));
44
+ }
45
+ });
46
+ }
47
+ finally {
48
+ intoCon.unref();
49
+ }
50
+ }
51
+ async retrieveFields() {
52
+ const intoCon = (0, intl_connection_js_1.getIntlConnection)(this.connection);
53
+ intoCon.ref();
54
+ try {
55
+ const socket = intoCon.socket;
56
+ socket.sendDescribeMessage({ type: 'P', name: this.name });
57
+ socket.sendFlushMessage();
58
+ return await socket.capture(async (code, msg, done) => {
59
+ switch (code) {
60
+ case protocol_js_1.Protocol.BackendMessageCode.NoticeResponse:
61
+ break;
62
+ case protocol_js_1.Protocol.BackendMessageCode.NoData:
63
+ done();
64
+ break;
65
+ case protocol_js_1.Protocol.BackendMessageCode.RowDescription:
66
+ done(undefined, msg.fields);
67
+ break;
68
+ default:
69
+ done(new Error(`Server returned unexpected response message (${String.fromCharCode(code)})`));
70
+ }
71
+ });
72
+ }
73
+ finally {
74
+ intoCon.unref();
75
+ }
76
+ }
77
+ async execute(fetchCount) {
78
+ const intoCon = (0, intl_connection_js_1.getIntlConnection)(this.connection);
79
+ intoCon.ref();
80
+ try {
81
+ const socket = intoCon.socket;
82
+ socket.sendExecuteMessage({ portal: this.name, fetchCount: fetchCount || 100 });
83
+ socket.sendFlushMessage();
84
+ const rows = [];
85
+ return await socket.capture(async (code, msg, done) => {
86
+ switch (code) {
87
+ case protocol_js_1.Protocol.BackendMessageCode.NoticeResponse:
88
+ break;
89
+ case protocol_js_1.Protocol.BackendMessageCode.NoData:
90
+ done(undefined, { code });
91
+ break;
92
+ case protocol_js_1.Protocol.BackendMessageCode.DataRow:
93
+ if (Array.isArray(this._columnFormat)) {
94
+ rows.push(msg.columns.map((buf, i) => this._columnFormat[i] === protocol_js_1.Protocol.DataFormat.text ? buf.toString('utf8') : buf));
95
+ }
96
+ else if (this._columnFormat === protocol_js_1.Protocol.DataFormat.binary)
97
+ rows.push(msg.columns);
98
+ else
99
+ rows.push(msg.columns.map((buf) => buf.toString('utf8')));
100
+ break;
101
+ case protocol_js_1.Protocol.BackendMessageCode.PortalSuspended:
102
+ done(undefined, { code, rows });
103
+ break;
104
+ case protocol_js_1.Protocol.BackendMessageCode.CommandComplete:
105
+ done(undefined, {
106
+ code,
107
+ rows,
108
+ command: msg.command,
109
+ rowCount: msg.rowCount,
110
+ });
111
+ break;
112
+ default:
113
+ done(new Error(`Server returned unexpected response message (${String.fromCharCode(code)})`));
114
+ }
115
+ });
116
+ }
117
+ finally {
118
+ intoCon.unref();
119
+ }
120
+ }
121
+ async close() {
122
+ const intoCon = (0, intl_connection_js_1.getIntlConnection)(this.connection);
123
+ intoCon.ref();
124
+ try {
125
+ const socket = intoCon.socket;
126
+ socket.sendCloseMessage({ type: 'P', name: this.name });
127
+ socket.sendSyncMessage();
128
+ return await socket.capture(async (code, msg, done) => {
129
+ switch (code) {
130
+ case protocol_js_1.Protocol.BackendMessageCode.NoticeResponse:
131
+ break;
132
+ case protocol_js_1.Protocol.BackendMessageCode.CloseComplete:
133
+ break;
134
+ case protocol_js_1.Protocol.BackendMessageCode.ReadyForQuery:
135
+ intoCon.transactionStatus = msg.status;
136
+ done();
137
+ break;
138
+ default:
139
+ done(new Error(`Server returned unexpected response message (${String.fromCharCode(code)})`));
140
+ }
141
+ });
142
+ }
143
+ finally {
144
+ intoCon.unref();
145
+ }
146
+ }
147
+ }
148
+ exports.Portal = Portal;