@depup/pg-promise 12.6.2-depup.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.
- package/LICENSE +21 -0
- package/README.md +25 -0
- package/lib/assert.js +10 -0
- package/lib/connect.js +178 -0
- package/lib/context.js +93 -0
- package/lib/database-pool.js +115 -0
- package/lib/database.js +1643 -0
- package/lib/errors/README.md +13 -0
- package/lib/errors/index.js +51 -0
- package/lib/errors/parameterized-query-error.js +71 -0
- package/lib/errors/prepared-statement-error.js +71 -0
- package/lib/errors/query-file-error.js +75 -0
- package/lib/errors/query-result-error.js +157 -0
- package/lib/events.js +543 -0
- package/lib/formatting.js +932 -0
- package/lib/helpers/README.md +10 -0
- package/lib/helpers/column-set.js +614 -0
- package/lib/helpers/column.js +406 -0
- package/lib/helpers/index.js +75 -0
- package/lib/helpers/methods/concat.js +103 -0
- package/lib/helpers/methods/index.js +13 -0
- package/lib/helpers/methods/insert.js +151 -0
- package/lib/helpers/methods/sets.js +81 -0
- package/lib/helpers/methods/update.js +248 -0
- package/lib/helpers/methods/values.js +116 -0
- package/lib/helpers/table-name.js +175 -0
- package/lib/index.js +29 -0
- package/lib/inner-state.js +39 -0
- package/lib/main.js +394 -0
- package/lib/patterns.js +43 -0
- package/lib/query-file.js +379 -0
- package/lib/query-result.js +39 -0
- package/lib/query.js +273 -0
- package/lib/special-query.js +30 -0
- package/lib/stream.js +125 -0
- package/lib/task.js +404 -0
- package/lib/text.js +40 -0
- package/lib/tx-mode.js +194 -0
- package/lib/types/index.js +18 -0
- package/lib/types/parameterized-query.js +247 -0
- package/lib/types/prepared-statement.js +298 -0
- package/lib/types/server-formatting.js +92 -0
- package/lib/utils/README.md +13 -0
- package/lib/utils/color.js +68 -0
- package/lib/utils/index.js +199 -0
- package/lib/utils/public.js +312 -0
- package/package.json +77 -0
- package/typescript/README.md +63 -0
- package/typescript/pg-promise.d.ts +728 -0
- package/typescript/pg-subset.d.ts +359 -0
- package/typescript/tslint.json +21 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015-present, Vitaly Tomilov
|
|
3
|
+
*
|
|
4
|
+
* See the LICENSE file at the top-level directory of this distribution
|
|
5
|
+
* for licensing information.
|
|
6
|
+
*
|
|
7
|
+
* Removal or modification of this copyright notice is prohibited.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const specialQueryType = {
|
|
11
|
+
result: 0,
|
|
12
|
+
multiResult: 1,
|
|
13
|
+
stream: 2
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
class SpecialQuery {
|
|
17
|
+
constructor(type) {
|
|
18
|
+
this.isResult = type === specialQueryType.result; // type used implicitly
|
|
19
|
+
this.isStream = type === specialQueryType.stream;
|
|
20
|
+
this.isMultiResult = type === specialQueryType.multiResult;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const cache = {
|
|
25
|
+
resultQuery: new SpecialQuery(specialQueryType.result),
|
|
26
|
+
multiResultQuery: new SpecialQuery(specialQueryType.multiResult),
|
|
27
|
+
streamQuery: new SpecialQuery(specialQueryType.stream)
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
module.exports = {SpecialQuery, ...cache};
|
package/lib/stream.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015-present, Vitaly Tomilov
|
|
3
|
+
*
|
|
4
|
+
* See the LICENSE file at the top-level directory of this distribution
|
|
5
|
+
* for licensing information.
|
|
6
|
+
*
|
|
7
|
+
* Removal or modification of this copyright notice is prohibited.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const {Events} = require('./events');
|
|
11
|
+
|
|
12
|
+
const npm = {
|
|
13
|
+
utils: require('./utils'),
|
|
14
|
+
text: require('./text')
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
////////////////////////////////////////////
|
|
18
|
+
// Streams query data into any destination,
|
|
19
|
+
// with the help of pg-query-stream library.
|
|
20
|
+
function $stream(ctx, qs, initCB) {
|
|
21
|
+
|
|
22
|
+
// istanbul ignore next:
|
|
23
|
+
// we do not provide code coverage for the Native Bindings specifics
|
|
24
|
+
if (ctx.options.pgNative) {
|
|
25
|
+
return Promise.reject(new Error(npm.text.nativeStreaming));
|
|
26
|
+
}
|
|
27
|
+
// Stream class was renamed again, see the following issue:
|
|
28
|
+
// https://github.com/brianc/node-postgres/issues/2412
|
|
29
|
+
if (!qs || !qs.constructor || qs.constructor.name !== 'QueryStream') {
|
|
30
|
+
// invalid or missing stream object;
|
|
31
|
+
return Promise.reject(new TypeError(npm.text.invalidStream));
|
|
32
|
+
}
|
|
33
|
+
if (qs._reading || qs._closed) {
|
|
34
|
+
// stream object is in the wrong state;
|
|
35
|
+
return Promise.reject(new Error(npm.text.invalidStreamState));
|
|
36
|
+
}
|
|
37
|
+
if (typeof initCB !== 'function') {
|
|
38
|
+
// parameter `initCB` must be passed as the initialization callback;
|
|
39
|
+
return Promise.reject(new TypeError(npm.text.invalidStreamCB));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let error = Events.query(ctx.options, getContext());
|
|
43
|
+
|
|
44
|
+
if (error) {
|
|
45
|
+
error = getError(error);
|
|
46
|
+
Events.error(ctx.options, error, getContext());
|
|
47
|
+
return Promise.reject(error);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const stream = ctx.db.client.query(qs);
|
|
51
|
+
|
|
52
|
+
stream.on('data', onData);
|
|
53
|
+
stream.on('error', onError);
|
|
54
|
+
stream.on('end', onEnd);
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
initCB.call(this, stream); // the stream must be initialized during the call;
|
|
58
|
+
} catch (e) {
|
|
59
|
+
release();
|
|
60
|
+
error = getError(e);
|
|
61
|
+
Events.error(ctx.options, error, getContext());
|
|
62
|
+
return Promise.reject(error);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const start = Date.now();
|
|
66
|
+
let resolve, reject, nRows = 0;
|
|
67
|
+
|
|
68
|
+
function onData(data) {
|
|
69
|
+
nRows++;
|
|
70
|
+
error = Events.receive(ctx.options, [data], undefined, getContext());
|
|
71
|
+
if (error) {
|
|
72
|
+
onError(error);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function onError(e) {
|
|
77
|
+
release();
|
|
78
|
+
stream.destroy();
|
|
79
|
+
e = getError(e);
|
|
80
|
+
Events.error(ctx.options, e, getContext());
|
|
81
|
+
reject(e);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function onEnd() {
|
|
85
|
+
release();
|
|
86
|
+
resolve({
|
|
87
|
+
processed: nRows, // total number of rows processed;
|
|
88
|
+
duration: Date.now() - start // duration, in milliseconds;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function release() {
|
|
93
|
+
stream.removeListener('data', onData);
|
|
94
|
+
stream.removeListener('error', onError);
|
|
95
|
+
stream.removeListener('end', onEnd);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function getError(e) {
|
|
99
|
+
return e instanceof npm.utils.InternalError ? e.error : e;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function getContext() {
|
|
103
|
+
let client;
|
|
104
|
+
if (ctx.db) {
|
|
105
|
+
client = ctx.db.client;
|
|
106
|
+
} else {
|
|
107
|
+
error = new Error(npm.text.looseQuery);
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
client,
|
|
111
|
+
dc: ctx.dc,
|
|
112
|
+
query: qs.cursor.text,
|
|
113
|
+
params: qs.cursor.values,
|
|
114
|
+
ctx: ctx.ctx
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return new Promise((res, rej) => {
|
|
119
|
+
resolve = res;
|
|
120
|
+
reject = rej;
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
module.exports = {stream: $stream};
|
package/lib/task.js
ADDED
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015-present, Vitaly Tomilov
|
|
3
|
+
*
|
|
4
|
+
* See the LICENSE file at the top-level directory of this distribution
|
|
5
|
+
* for licensing information.
|
|
6
|
+
*
|
|
7
|
+
* Removal or modification of this copyright notice is prohibited.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const {Events} = require('./events');
|
|
11
|
+
|
|
12
|
+
const npm = {
|
|
13
|
+
spex: require('spex'),
|
|
14
|
+
utils: require('./utils'),
|
|
15
|
+
mode: require('./tx-mode'),
|
|
16
|
+
query: require('./query').query,
|
|
17
|
+
text: require('./text')
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @interface Task
|
|
22
|
+
* @description
|
|
23
|
+
* Extends {@link Database} for an automatic connection session, with methods for executing multiple database queries.
|
|
24
|
+
*
|
|
25
|
+
* The type isn't available directly, it can only be created via methods {@link Database#task Database.task}, {@link Database#tx Database.tx},
|
|
26
|
+
* or their derivations.
|
|
27
|
+
*
|
|
28
|
+
* When executing more than one request at a time, one should allocate and release the connection only once,
|
|
29
|
+
* while executing all the required queries within the same connection session. More importantly, a transaction
|
|
30
|
+
* can only work within a single connection.
|
|
31
|
+
*
|
|
32
|
+
* This is an interface for tasks/transactions to implement a connection session, during which you can
|
|
33
|
+
* execute multiple queries against the same connection that's released automatically when the task/transaction is finished.
|
|
34
|
+
*
|
|
35
|
+
* Each task/transaction manages the connection automatically. When executed on the root {@link Database} object, the connection
|
|
36
|
+
* is allocated from the pool, and once the method's callback has finished, the connection is released back to the pool.
|
|
37
|
+
* However, when invoked inside another task or transaction, the method reuses the parent connection.
|
|
38
|
+
*
|
|
39
|
+
* @see
|
|
40
|
+
* {@link Task#ctx ctx},
|
|
41
|
+
* {@link Task#batch batch},
|
|
42
|
+
* {@link Task#sequence sequence},
|
|
43
|
+
* {@link Task#page page}
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* db.task(t => {
|
|
47
|
+
* // t = task protocol context;
|
|
48
|
+
* // t.ctx = Task Context;
|
|
49
|
+
* return t.one('select * from users where id=$1', 123)
|
|
50
|
+
* .then(user => {
|
|
51
|
+
* return t.any('select * from events where login=$1', user.name);
|
|
52
|
+
* });
|
|
53
|
+
* })
|
|
54
|
+
* .then(events => {
|
|
55
|
+
* // success;
|
|
56
|
+
* })
|
|
57
|
+
* .catch(error => {
|
|
58
|
+
* // error;
|
|
59
|
+
* });
|
|
60
|
+
*
|
|
61
|
+
*/
|
|
62
|
+
function Task(ctx, tag, isTX, config) {
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @member {TaskContext} Task#ctx
|
|
66
|
+
* @readonly
|
|
67
|
+
* @description
|
|
68
|
+
* Task/Transaction Context object - contains individual properties for each task/transaction.
|
|
69
|
+
*
|
|
70
|
+
* @see event {@link event:query query}
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
*
|
|
74
|
+
* db.task(t => {
|
|
75
|
+
* return t.ctx; // task context object
|
|
76
|
+
* })
|
|
77
|
+
* .then(ctx => {
|
|
78
|
+
* console.log('Task Duration:', ctx.duration);
|
|
79
|
+
* });
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
*
|
|
83
|
+
* db.tx(t => {
|
|
84
|
+
* return t.ctx; // transaction context object
|
|
85
|
+
* })
|
|
86
|
+
* .then(ctx => {
|
|
87
|
+
* console.log('Transaction Duration:', ctx.duration);
|
|
88
|
+
* });
|
|
89
|
+
*/
|
|
90
|
+
this.ctx = ctx.ctx = {}; // task context object;
|
|
91
|
+
|
|
92
|
+
npm.utils.addReadProp(this.ctx, 'isTX', isTX);
|
|
93
|
+
|
|
94
|
+
if ('context' in ctx) {
|
|
95
|
+
npm.utils.addReadProp(this.ctx, 'context', ctx.context);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
npm.utils.addReadProp(this.ctx, 'connected', !ctx.db);
|
|
99
|
+
npm.utils.addReadProp(this.ctx, 'tag', tag);
|
|
100
|
+
npm.utils.addReadProp(this.ctx, 'dc', ctx.dc);
|
|
101
|
+
npm.utils.addReadProp(this.ctx, 'level', ctx.level);
|
|
102
|
+
npm.utils.addReadProp(this.ctx, 'inTransaction', ctx.inTransaction);
|
|
103
|
+
|
|
104
|
+
if (isTX) {
|
|
105
|
+
npm.utils.addReadProp(this.ctx, 'txLevel', ctx.txLevel);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
npm.utils.addReadProp(this.ctx, 'parent', ctx.parentCtx);
|
|
109
|
+
|
|
110
|
+
// generic query method;
|
|
111
|
+
this.query = function (query, values, qrm) {
|
|
112
|
+
if (!ctx.db) {
|
|
113
|
+
return Promise.reject(new Error(npm.text.looseQuery));
|
|
114
|
+
}
|
|
115
|
+
return config.$npm.query.call(this, ctx, query, values, qrm);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @method Task#batch
|
|
120
|
+
* @description
|
|
121
|
+
* Settles a predefined array of mixed values by redirecting to method $[spex.batch].
|
|
122
|
+
*
|
|
123
|
+
* **NOTE:**
|
|
124
|
+
* Consider using `async/await` syntax instead, or if you must have
|
|
125
|
+
* pre-generated promises, then $[Promise.allSettled].
|
|
126
|
+
*
|
|
127
|
+
* @param {array} values
|
|
128
|
+
* @param {Object} [options]
|
|
129
|
+
* Optional Parameters.
|
|
130
|
+
* @param {function} [options.cb]
|
|
131
|
+
*
|
|
132
|
+
* @returns {external:Promise}
|
|
133
|
+
*/
|
|
134
|
+
this.batch = function (values, options) {
|
|
135
|
+
return config.$npm.spex.batch.call(this, values, options);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @method Task#page
|
|
140
|
+
* @description
|
|
141
|
+
* Resolves a dynamic sequence of arrays/pages with mixed values, by redirecting to method $[spex.page].
|
|
142
|
+
*
|
|
143
|
+
* For complete method documentation see $[spex.page].
|
|
144
|
+
*
|
|
145
|
+
* @param {function} source
|
|
146
|
+
* @param {Object} [options]
|
|
147
|
+
* Optional Parameters.
|
|
148
|
+
* @param {function} [options.dest]
|
|
149
|
+
* @param {number} [options.limit=0]
|
|
150
|
+
*
|
|
151
|
+
* @returns {external:Promise}
|
|
152
|
+
*/
|
|
153
|
+
this.page = function (source, options) {
|
|
154
|
+
return config.$npm.spex.page.call(this, source, options);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* @method Task#sequence
|
|
159
|
+
* @description
|
|
160
|
+
* Resolves a dynamic sequence of mixed values by redirecting to method $[spex.sequence].
|
|
161
|
+
*
|
|
162
|
+
* For complete method documentation see $[spex.sequence].
|
|
163
|
+
*
|
|
164
|
+
* @param {function} source
|
|
165
|
+
* @param {Object} [options]
|
|
166
|
+
* Optional Parameters.
|
|
167
|
+
* @param {function} [options.dest]
|
|
168
|
+
* @param {number} [options.limit=0]
|
|
169
|
+
* @param {boolean} [options.track=false]
|
|
170
|
+
*
|
|
171
|
+
* @returns {external:Promise}
|
|
172
|
+
*/
|
|
173
|
+
this.sequence = function (source, options) {
|
|
174
|
+
return config.$npm.spex.sequence.call(this, source, options);
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* @private
|
|
181
|
+
* @method Task.callback
|
|
182
|
+
* Callback invocation helper.
|
|
183
|
+
*
|
|
184
|
+
* @param ctx
|
|
185
|
+
* @param obj
|
|
186
|
+
* @param cb
|
|
187
|
+
* @param config
|
|
188
|
+
* @returns {Promise.<TResult>}
|
|
189
|
+
*/
|
|
190
|
+
const callback = (ctx, obj, cb) => {
|
|
191
|
+
|
|
192
|
+
let result;
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
if (cb.constructor.name === 'GeneratorFunction') {
|
|
196
|
+
throw new TypeError('ES6 generator functions are not supported!');
|
|
197
|
+
}
|
|
198
|
+
result = cb.call(obj, obj); // invoking the callback function;
|
|
199
|
+
} catch (err) {
|
|
200
|
+
Events.error(ctx.options, err, {
|
|
201
|
+
client: ctx.db && ctx.db.client, // the error can be due to loss of connectivity
|
|
202
|
+
dc: ctx.dc,
|
|
203
|
+
ctx: ctx.ctx
|
|
204
|
+
});
|
|
205
|
+
return Promise.reject(err); // reject with the error;
|
|
206
|
+
}
|
|
207
|
+
if (result instanceof Promise) {
|
|
208
|
+
return result; // result is a valid promise object;
|
|
209
|
+
}
|
|
210
|
+
return Promise.resolve(result);
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* @private
|
|
215
|
+
* @method Task.execute
|
|
216
|
+
* Executes a task.
|
|
217
|
+
*
|
|
218
|
+
* @param ctx
|
|
219
|
+
* @param obj
|
|
220
|
+
* @param isTX
|
|
221
|
+
* @param config
|
|
222
|
+
* @returns {Promise.<TResult>}
|
|
223
|
+
*/
|
|
224
|
+
const execute = (ctx, obj, isTX, config) => {
|
|
225
|
+
|
|
226
|
+
// updates the task context and notifies the client;
|
|
227
|
+
function update(start, success, result) {
|
|
228
|
+
const c = ctx.ctx;
|
|
229
|
+
if (start) {
|
|
230
|
+
npm.utils.addReadProp(c, 'start', new Date());
|
|
231
|
+
} else {
|
|
232
|
+
c.finish = new Date();
|
|
233
|
+
c.success = success;
|
|
234
|
+
c.result = result;
|
|
235
|
+
c.duration = c.finish - c.start;
|
|
236
|
+
}
|
|
237
|
+
(isTX ? Events.transact : Events.task)(ctx.options, {
|
|
238
|
+
client: ctx.db && ctx.db.client, // loss of connectivity is possible at this point
|
|
239
|
+
dc: ctx.dc,
|
|
240
|
+
ctx: c
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
let cbData, cbReason, success,
|
|
245
|
+
spName; // Save-Point Name;
|
|
246
|
+
|
|
247
|
+
const capSQL = ctx.options.capSQL; // capitalize sql;
|
|
248
|
+
|
|
249
|
+
update(true);
|
|
250
|
+
|
|
251
|
+
if (isTX) {
|
|
252
|
+
// executing a transaction;
|
|
253
|
+
spName = `sp_${ctx.txLevel}_${ctx.nextTxCount}`;
|
|
254
|
+
return begin()
|
|
255
|
+
.then(() => callback(ctx, obj, ctx.cb, config)
|
|
256
|
+
.then(data => {
|
|
257
|
+
cbData = data; // save callback data;
|
|
258
|
+
success = true;
|
|
259
|
+
return commit();
|
|
260
|
+
}, err => {
|
|
261
|
+
cbReason = err; // save callback failure reason;
|
|
262
|
+
return rollback();
|
|
263
|
+
})
|
|
264
|
+
.then(() => {
|
|
265
|
+
if (success) {
|
|
266
|
+
update(false, true, cbData);
|
|
267
|
+
return cbData;
|
|
268
|
+
}
|
|
269
|
+
update(false, false, cbReason);
|
|
270
|
+
return Promise.reject(cbReason);
|
|
271
|
+
},
|
|
272
|
+
err => {
|
|
273
|
+
// either COMMIT or ROLLBACK has failed, which is impossible
|
|
274
|
+
// to replicate in a test environment, so skipping from the test;
|
|
275
|
+
// istanbul ignore next:
|
|
276
|
+
update(false, false, err);
|
|
277
|
+
// istanbul ignore next:
|
|
278
|
+
return Promise.reject(err);
|
|
279
|
+
}),
|
|
280
|
+
err => {
|
|
281
|
+
// BEGIN has failed, which is impossible to replicate in a test
|
|
282
|
+
// environment, so skipping the whole block from the test;
|
|
283
|
+
// istanbul ignore next:
|
|
284
|
+
update(false, false, err);
|
|
285
|
+
// istanbul ignore next:
|
|
286
|
+
return Promise.reject(err);
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function begin() {
|
|
291
|
+
if (!ctx.txLevel && ctx.mode instanceof npm.mode.TransactionMode) {
|
|
292
|
+
return exec(ctx.mode.begin(capSQL), 'savepoint');
|
|
293
|
+
}
|
|
294
|
+
return exec('begin', 'savepoint');
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function commit() {
|
|
298
|
+
return exec('commit', 'release savepoint');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function rollback() {
|
|
302
|
+
return exec('rollback', 'rollback to savepoint');
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function exec(top, nested) {
|
|
306
|
+
if (ctx.txLevel) {
|
|
307
|
+
return obj.none((capSQL ? nested.toUpperCase() : nested) + ' ' + spName);
|
|
308
|
+
}
|
|
309
|
+
return obj.none(capSQL ? top.toUpperCase() : top);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// executing a task;
|
|
313
|
+
return callback(ctx, obj, ctx.cb, config)
|
|
314
|
+
.then(data => {
|
|
315
|
+
update(false, true, data);
|
|
316
|
+
return data;
|
|
317
|
+
})
|
|
318
|
+
.catch(error => {
|
|
319
|
+
update(false, false, error);
|
|
320
|
+
return Promise.reject(error);
|
|
321
|
+
});
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
module.exports = config => {
|
|
325
|
+
const npmLocal = config.$npm;
|
|
326
|
+
npmLocal.query = npmLocal.query || npm.query;
|
|
327
|
+
npmLocal.spex = npmLocal.spex || npm.spex;
|
|
328
|
+
return {
|
|
329
|
+
Task, execute, callback
|
|
330
|
+
};
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* @typedef TaskContext
|
|
335
|
+
* @description
|
|
336
|
+
* Task/Transaction Context used via property {@link Task#ctx ctx} inside tasks (methods {@link Database#task Database.task} and {@link Database#taskIf Database.taskIf})
|
|
337
|
+
* and transactions (methods {@link Database#tx Database.tx} and {@link Database#txIf Database.txIf}).
|
|
338
|
+
*
|
|
339
|
+
* Properties `context`, `connected`, `parent`, `level`, `dc`, `isTX`, `tag`, `start`, `useCount` and `serverVersion` are set just before the operation has started,
|
|
340
|
+
* while properties `finish`, `duration`, `success` and `result` are set immediately after the operation has finished.
|
|
341
|
+
*
|
|
342
|
+
* @property {*} context
|
|
343
|
+
* If the operation was invoked with a calling context - `task.call(context,...)` or `tx.call(context,...)`,
|
|
344
|
+
* this property is set with the context that was passed in. Otherwise, the property doesn't exist.
|
|
345
|
+
*
|
|
346
|
+
* @property {*} dc
|
|
347
|
+
* _Database Context_ that was passed into the {@link Database} object during construction.
|
|
348
|
+
*
|
|
349
|
+
* @property {boolean} isTX
|
|
350
|
+
* Indicates whether this operation is a transaction (as opposed to a regular task).
|
|
351
|
+
*
|
|
352
|
+
* @property {number} duration
|
|
353
|
+
* Number of milliseconds consumed by the operation.
|
|
354
|
+
*
|
|
355
|
+
* Set after the operation has finished, it is simply a shortcut for `finish - start`.
|
|
356
|
+
*
|
|
357
|
+
* @property {number} level
|
|
358
|
+
* Task nesting level, starting from 0, counting both regular tasks and transactions.
|
|
359
|
+
*
|
|
360
|
+
* @property {number} txLevel
|
|
361
|
+
* Transaction nesting level, starting from 0. Transactions on level 0 use `BEGIN/COMMIT/ROLLBACK`,
|
|
362
|
+
* while transactions on nested levels use the corresponding `SAVEPOINT` commands.
|
|
363
|
+
*
|
|
364
|
+
* This property exists only within the context of a transaction (`isTX = true`).
|
|
365
|
+
*
|
|
366
|
+
* @property {boolean} inTransaction
|
|
367
|
+
* Available in both tasks and transactions, it simplifies checking when there is a transaction
|
|
368
|
+
* going on either on this level or above.
|
|
369
|
+
*
|
|
370
|
+
* For example, when you want to check for a containing transaction while inside a task, and
|
|
371
|
+
* only start a transaction when there is none yet.
|
|
372
|
+
*
|
|
373
|
+
* @property {TaskContext} parent
|
|
374
|
+
* Parent task/transaction context, or `null` when it is top-level.
|
|
375
|
+
*
|
|
376
|
+
* @property {boolean} connected
|
|
377
|
+
* Indicates when the task/transaction acquired the connection on its own (`connected = true`), and will release it once
|
|
378
|
+
* the operation has finished. When the value is `false`, the operation is reusing an existing connection.
|
|
379
|
+
*
|
|
380
|
+
* @property {*} tag
|
|
381
|
+
* Tag value as it was passed into the task. See methods {@link Database#task task} and {@link Database#tx tx}.
|
|
382
|
+
*
|
|
383
|
+
* @property {Date} start
|
|
384
|
+
* Date/Time of when this operation started the execution.
|
|
385
|
+
*
|
|
386
|
+
* @property {number} useCount
|
|
387
|
+
* Number of times the connection has been previously used, starting with 0 for a freshly
|
|
388
|
+
* allocated physical connection.
|
|
389
|
+
*
|
|
390
|
+
* @property {string} serverVersion
|
|
391
|
+
* Version of the PostgreSQL server to which we are connected.
|
|
392
|
+
* Not available with $[Native Bindings].
|
|
393
|
+
*
|
|
394
|
+
* @property {Date} finish
|
|
395
|
+
* Once the operation has finished, this property is set to the Data/Time of when it happened.
|
|
396
|
+
*
|
|
397
|
+
* @property {boolean} success
|
|
398
|
+
* Once the operation has finished, this property indicates whether it was successful.
|
|
399
|
+
*
|
|
400
|
+
* @property {*} result
|
|
401
|
+
* Once the operation has finished, this property contains the result, depending on property `success`:
|
|
402
|
+
* - data resolved by the operation, if `success = true`
|
|
403
|
+
* - error / rejection reason, if `success = false`
|
|
404
|
+
*/
|
package/lib/text.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015-present, Vitaly Tomilov
|
|
3
|
+
*
|
|
4
|
+
* See the LICENSE file at the top-level directory of this distribution
|
|
5
|
+
* for licensing information.
|
|
6
|
+
*
|
|
7
|
+
* Removal or modification of this copyright notice is prohibited.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/* All error messages used in the module */
|
|
11
|
+
|
|
12
|
+
const streamVersion = require('../package.json')
|
|
13
|
+
.devDependencies['pg-query-stream'];
|
|
14
|
+
|
|
15
|
+
module.exports = {
|
|
16
|
+
nativeError: 'Failed to initialize Native Bindings.',
|
|
17
|
+
|
|
18
|
+
/* Database errors */
|
|
19
|
+
queryDisconnected: 'Cannot execute a query on a disconnected client.',
|
|
20
|
+
invalidQuery: 'Invalid query format.',
|
|
21
|
+
invalidFunction: 'Invalid function name.',
|
|
22
|
+
invalidProc: 'Invalid procedure name.',
|
|
23
|
+
invalidMask: 'Invalid Query Result Mask specified.',
|
|
24
|
+
looseQuery: 'Querying against a released or lost connection.',
|
|
25
|
+
|
|
26
|
+
/* result errors */
|
|
27
|
+
notEmpty: 'No return data was expected.',
|
|
28
|
+
noData: 'No data returned from the query.',
|
|
29
|
+
multiple: 'Multiple rows were not expected.',
|
|
30
|
+
|
|
31
|
+
/* streaming support */
|
|
32
|
+
nativeStreaming: 'Streaming doesn\'t work with Native Bindings.',
|
|
33
|
+
invalidStream: `Invalid or missing stream object: pg-query-stream >= v${streamVersion} was expected`,
|
|
34
|
+
invalidStreamState: 'Invalid stream state.',
|
|
35
|
+
invalidStreamCB: 'Invalid or missing stream initialization callback.',
|
|
36
|
+
|
|
37
|
+
/* connection errors */
|
|
38
|
+
poolDestroyed: 'Connection pool of the database object has been destroyed.',
|
|
39
|
+
clientEnd: 'Abnormal client.end() call, due to invalid code or failed server connection.'
|
|
40
|
+
};
|