node-firebird 1.1.8 → 1.1.9

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/lib/pool.js ADDED
@@ -0,0 +1,107 @@
1
+ /***************************************
2
+ *
3
+ * Simple Pooling
4
+ *
5
+ ***************************************/
6
+
7
+ function Pool(attach, max, options) {
8
+ this.attach = attach;
9
+ this.internaldb = []; // connection created by the pool (for destroy)
10
+ this.pooldb = []; // available connection in the pool
11
+ this.dbinuse = 0; // connection currently in use into the pool
12
+ this.max = max || 4;
13
+ this.pending = [];
14
+ this.options = options;
15
+ }
16
+
17
+ Pool.prototype.get = function(callback) {
18
+ var self = this;
19
+ self.pending.push(callback);
20
+ self.check();
21
+ return self;
22
+ };
23
+
24
+ Pool.prototype.check = function() {
25
+
26
+ var self = this;
27
+ if (self.dbinuse >= self.max)
28
+ return self;
29
+
30
+ var cb = self.pending.shift();
31
+ if (!cb)
32
+ return self;
33
+ self.dbinuse++;
34
+ if (self.pooldb.length) {
35
+ cb(null, self.pooldb.shift());
36
+ } else {
37
+ this.attach(self.options, function (err, db) {
38
+ if (!err) {
39
+ self.internaldb.push(db);
40
+ db.on('detach', function () {
41
+ // also in pool (could be a twice call to detach)
42
+ if (self.pooldb.indexOf(db) !== -1 || self.internaldb.indexOf(db) === -1)
43
+ return;
44
+ // if not usable don't put in again in the pool and remove reference on it
45
+ if (db.connection._isClosed || db.connection._isDetach || db.connection._pooled === false)
46
+ self.internaldb.splice(self.internaldb.indexOf(db), 1);
47
+ else
48
+ self.pooldb.push(db);
49
+
50
+ if (db.connection._pooled)
51
+ self.dbinuse--;
52
+ self.check();
53
+ });
54
+ } else {
55
+ // attach fail so not in the pool
56
+ self.dbinuse--;
57
+ }
58
+
59
+ cb(err, db);
60
+ });
61
+ }
62
+ setImmediate(function() {
63
+ self.check();
64
+ });
65
+
66
+ return self;
67
+ };
68
+
69
+ Pool.prototype.destroy = function(callback) {
70
+ var self = this;
71
+
72
+ var connectionCount = this.internaldb.length;
73
+
74
+ if (connectionCount === 0 && callback) {
75
+ callback();
76
+ }
77
+
78
+ function detachCallback(err) {
79
+ if (err) {
80
+ if (callback) {
81
+ callback(err);
82
+ }
83
+ return;
84
+ }
85
+
86
+ connectionCount--;
87
+ if (connectionCount === 0 && callback) {
88
+ callback();
89
+ }
90
+ }
91
+
92
+ this.internaldb.forEach(function(db) {
93
+ if (db.connection._pooled === false) {
94
+ detachCallback();
95
+ return;
96
+ }
97
+ // check if the db is not free into the pool otherwise user should manual detach it
98
+ var _db_in_pool = self.pooldb.indexOf(db);
99
+ if (_db_in_pool !== -1) {
100
+ self.pooldb.splice(_db_in_pool, 1);
101
+ db.connection._pooled = false;
102
+ db.detach(detachCallback);
103
+ }
104
+ });
105
+ };
106
+
107
+ module.exports = Pool;
package/lib/utils.js ADDED
@@ -0,0 +1,164 @@
1
+ const MessagesError = require('./firebird.msg.json');
2
+ const Const = require('./wire/const');
3
+
4
+ /**
5
+ * Parse date from string
6
+ * @param {String} str
7
+ * @return {Date}
8
+ */
9
+ const parseDate = (str) => {
10
+ const self = str.trim();
11
+ const arr = self.indexOf(' ') === -1 ? self.split('T') : self.split(' ');
12
+ let index = arr[0].indexOf(':');
13
+ const length = arr[0].length;
14
+
15
+ if (index !== -1) {
16
+ const tmp = arr[1];
17
+ arr[1] = arr[0];
18
+ arr[0] = tmp;
19
+ }
20
+
21
+ if (arr[0] === undefined) {
22
+ arr[0] = '';
23
+ }
24
+
25
+ const noTime = arr[1] === undefined || arr[1].length === 0;
26
+
27
+ for (let i = 0; i < length; i++) {
28
+ const c = arr[0].charCodeAt(i);
29
+ if (c > 47 && c < 58) {
30
+ continue;
31
+ }
32
+ if (c === 45 || c === 46) {
33
+ continue;
34
+ }
35
+ if (noTime) {
36
+ return new Date(self);
37
+ }
38
+ }
39
+
40
+ if (arr[1] === undefined) {
41
+ arr[1] = '00:00:00';
42
+ }
43
+
44
+ const firstDay = arr[0].indexOf('-') === -1;
45
+
46
+ const date = (arr[0] || '').split(firstDay ? '.' : '-');
47
+ const time = (arr[1] || '').split(':');
48
+
49
+ if (date.length < 4 && time.length < 2) {
50
+ return new Date(self);
51
+ }
52
+
53
+ index = (time[2] || '').indexOf('.');
54
+
55
+ // milliseconds
56
+ if (index !== -1) {
57
+ time[3] = time[2].substring(index + 1);
58
+ time[2] = time[2].substring(0, index);
59
+ } else {
60
+ time[3] = '0';
61
+ }
62
+
63
+ const parsed = [
64
+ parseInt(date[firstDay ? 2 : 0], 10), // year
65
+ parseInt(date[1], 10), // month
66
+ parseInt(date[firstDay ? 0 : 2], 10), // day
67
+ parseInt(time[0], 10), // hours
68
+ parseInt(time[1], 10), // minutes
69
+ parseInt(time[2], 10), // seconds
70
+ parseInt(time[3], 10) // miliseconds
71
+ ];
72
+
73
+ const def = new Date();
74
+
75
+ for (let i = 0; i < parsed.length; i++) {
76
+ if (isNaN(parsed[i])) {
77
+ parsed[i] = 0;
78
+ }
79
+
80
+ const value = parsed[i];
81
+ if (value !== 0) {
82
+ continue;
83
+ }
84
+
85
+ switch (i) {
86
+ case 0:
87
+ if (value <= 0) {
88
+ parsed[i] = def.getFullYear();
89
+ }
90
+ break;
91
+ case 1:
92
+ if (value <= 0) {
93
+ parsed[i] = def.getMonth() + 1;
94
+ }
95
+ break;
96
+ case 2:
97
+ if (value <= 0) {
98
+ parsed[i] = def.getDate();
99
+ }
100
+ break;
101
+ }
102
+ }
103
+
104
+ return new Date(parsed[0], parsed[1] - 1, parsed[2], parsed[3], parsed[4], parsed[5]);
105
+ }
106
+
107
+ /**
108
+ * Get Error Message per gdscode
109
+ * @param {{gdscode: Number, params: Any[]}[]} status
110
+ * @returns {String} - Error message
111
+ */
112
+ const lookupMessages = (status) => {
113
+ const messages = status.map((item) => {
114
+ let text = MessagesError[item.gdscode];
115
+ if (text === undefined) {
116
+ return 'Unknow error';
117
+ }
118
+ if (item.params !== undefined) {
119
+ item.params.forEach((param, i) => {
120
+ text = text.replace('@' + (i + 1), param);
121
+ });
122
+ }
123
+ return text;
124
+ });
125
+ return messages.join(', ');
126
+ }
127
+
128
+ /**
129
+ * Escape value
130
+ * @param {Object} value
131
+ * @param {Number} protocolVersion (optional, default: PROTOCOL_VERSION13)
132
+ * @return {String}
133
+ */
134
+ const escape = function(value, protocolVersion) {
135
+
136
+ if (value === null || value === undefined)
137
+ return 'NULL';
138
+
139
+ switch (typeof(value)) {
140
+ case 'boolean':
141
+ if ((protocolVersion || Const.PROTOCOL_VERSION13) >= Const.PROTOCOL_VERSION13)
142
+ return value ? 'true' : 'false';
143
+ else
144
+ return value ? '1' : '0';
145
+ case 'number':
146
+ return value.toString();
147
+ case 'string':
148
+ return "'" + value.replace(/'/g, "''").replace(/\\/g, '\\\\') + "'";
149
+ }
150
+
151
+ if (value instanceof Date)
152
+ return "'" + value.getFullYear() + '-' + (value.getMonth()+1).toString().padLeft(2, '0') + '-' + value.getDate().toString().padLeft(2, '0') + ' ' + value.getHours().toString().padLeft(2, '0') + ':' + value.getMinutes().toString().padLeft(2, '0') + ':' + value.getSeconds().toString().padLeft(2, '0') + '.' + value.getMilliseconds().toString().padLeft(3, '0') + "'";
153
+
154
+ throw new Error('Escape supports only primitive values.');
155
+ };
156
+
157
+ function noop() {}
158
+
159
+ module.exports = {
160
+ escape,
161
+ lookupMessages,
162
+ noop,
163
+ parseDate,
164
+ };