monetdb 1.3.4 → 2.0.1
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/.github/workflows/Linux.yml +3 -3
- package/.github/workflows/docs.yml +79 -0
- package/.github/workflows/macos.yml +3 -3
- package/.github/workflows/monetdb-versions.yml +43 -0
- package/README.md +44 -514
- package/docs/components/alert.tsx +10 -0
- package/docs/components/info.tsx +6 -0
- package/docs/next.config.js +24 -0
- package/docs/package-lock.json +5069 -0
- package/docs/package.json +22 -0
- package/docs/pages/_app.js +9 -0
- package/docs/pages/_meta.json +18 -0
- package/docs/pages/apis/_meta.json +4 -0
- package/docs/pages/apis/connection.mdx +60 -0
- package/docs/pages/apis/result.mdx +39 -0
- package/docs/pages/filetransfer.mdx +43 -0
- package/docs/pages/index.mdx +27 -0
- package/docs/pages/prepstmt.mdx +13 -0
- package/docs/pages/result.mdx +41 -0
- package/docs/theme.config.js +35 -0
- package/docs/v1/README.md +532 -0
- package/package.json +16 -20
- package/src/PrepareStatement.ts +37 -0
- package/src/connection.ts +125 -0
- package/src/defaults.ts +11 -0
- package/src/file-transfer.ts +173 -0
- package/src/index.ts +3 -0
- package/src/mapi.ts +1016 -0
- package/src/monetize.ts +67 -0
- package/test/connection.ts +43 -0
- package/test/exec-queries.ts +112 -0
- package/test/filetransfer.ts +94 -0
- package/test/prepare-statement.ts +27 -0
- package/test/query-stream.ts +41 -0
- package/test/tmp/.gitignore +4 -0
- package/tsconfig.json +24 -0
- package/.travis.yml +0 -11
- package/dist/mapi.d.ts +0 -58
- package/dist/mapi.js +0 -250
- package/dist/mapi.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/foo.js +0 -16
- package/index.js +0 -5
- package/src/mapi-connection.js +0 -784
- package/src/monetdb-connection.js +0 -385
- package/src/utils.js +0 -27
- package/test/common.js +0 -45
- package/test/install-monetdb.sh +0 -11
- package/test/monetdb_stream.js +0 -106
- package/test/start-monetdb.sh +0 -38
- package/test/test.js +0 -908
- package/test/test_connection.js +0 -290
- /package/docs/{README.v0.md → v0/README.v0.md} +0 -0
- /package/docs/{MapiConnection.md → v1/MapiConnection.md} +0 -0
- /package/docs/{v1-notes.md → v1/v1-notes.md} +0 -0
@@ -1,385 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Author: Robin Cijvat <robin.cijvat@monetdbsolutions.com>
|
3
|
-
*/
|
4
|
-
|
5
|
-
'use strict';
|
6
|
-
|
7
|
-
var Q = require('q');
|
8
|
-
|
9
|
-
var utils = require('./utils.js');
|
10
|
-
var MapiConnection = require('./mapi-connection.js');
|
11
|
-
|
12
|
-
var optionDefinition = {
|
13
|
-
host: {
|
14
|
-
type: 'string',
|
15
|
-
dflt: 'localhost'
|
16
|
-
},
|
17
|
-
port: {
|
18
|
-
type: 'number',
|
19
|
-
dflt: 50000,
|
20
|
-
transform: parseInt
|
21
|
-
},
|
22
|
-
dbname: {
|
23
|
-
type: 'string'
|
24
|
-
},
|
25
|
-
user: {
|
26
|
-
type: 'string',
|
27
|
-
dflt: 'monetdb'
|
28
|
-
},
|
29
|
-
password: {
|
30
|
-
type: 'string',
|
31
|
-
dflt: 'monetdb'
|
32
|
-
},
|
33
|
-
language: {
|
34
|
-
type: 'string',
|
35
|
-
dflt: 'sql'
|
36
|
-
},
|
37
|
-
defaultSchema: {
|
38
|
-
type: 'string',
|
39
|
-
dflt: 'sys'
|
40
|
-
},
|
41
|
-
timezoneOffset: {
|
42
|
-
type: 'number',
|
43
|
-
dflt: new Date().getTimezoneOffset(), // offset in minutes
|
44
|
-
transform: parseInt
|
45
|
-
},
|
46
|
-
maxReconnects: {
|
47
|
-
type: 'number',
|
48
|
-
dflt: 10,
|
49
|
-
transform: parseInt,
|
50
|
-
changeable: true
|
51
|
-
},
|
52
|
-
reconnectTimeout: {
|
53
|
-
type: 'number',
|
54
|
-
dflt: 2000,
|
55
|
-
transform: parseInt,
|
56
|
-
changeable: true
|
57
|
-
},
|
58
|
-
prettyResult: {
|
59
|
-
type: 'boolean',
|
60
|
-
dflt: false,
|
61
|
-
transform: parseBool,
|
62
|
-
changeable: true
|
63
|
-
},
|
64
|
-
logger: {
|
65
|
-
type: 'function',
|
66
|
-
dflt: console.log,
|
67
|
-
changeable: true
|
68
|
-
},
|
69
|
-
warnings: {
|
70
|
-
type: 'boolean',
|
71
|
-
dflt: true,
|
72
|
-
transform: parseBool,
|
73
|
-
changeable: true
|
74
|
-
},
|
75
|
-
warningFn: {
|
76
|
-
type: 'function',
|
77
|
-
dflt: utils.warning,
|
78
|
-
changeable: true
|
79
|
-
},
|
80
|
-
debug: {
|
81
|
-
type: 'boolean',
|
82
|
-
dflt: false,
|
83
|
-
transform: parseBool,
|
84
|
-
changeable: true
|
85
|
-
},
|
86
|
-
debugFn: {
|
87
|
-
type: 'function',
|
88
|
-
dflt: utils.debug,
|
89
|
-
changeable: true
|
90
|
-
},
|
91
|
-
debugRequests: {
|
92
|
-
type: 'boolean',
|
93
|
-
dflt: false,
|
94
|
-
transform: parseBool,
|
95
|
-
changeable: true
|
96
|
-
},
|
97
|
-
debugRequestFn: {
|
98
|
-
type: 'function',
|
99
|
-
dflt: utils.debugRequest,
|
100
|
-
changeable: true
|
101
|
-
},
|
102
|
-
debugMapi: {
|
103
|
-
type: 'boolean',
|
104
|
-
dflt: false,
|
105
|
-
transform: parseBool,
|
106
|
-
changeable: true
|
107
|
-
},
|
108
|
-
debugMapiFn: {
|
109
|
-
type: 'function',
|
110
|
-
dflt: utils.debugMapi,
|
111
|
-
changeable: true
|
112
|
-
},
|
113
|
-
testing: {
|
114
|
-
type: 'boolean',
|
115
|
-
dflt: false,
|
116
|
-
transform: parseBool
|
117
|
-
},
|
118
|
-
autoCommit: {
|
119
|
-
type: 'boolean',
|
120
|
-
dflt: true, // by default auto_commit=1 see mclient.c
|
121
|
-
transform: parseBool
|
122
|
-
}
|
123
|
-
};
|
124
|
-
|
125
|
-
var apiAliases = [
|
126
|
-
{ from: "open", to: "connect" },
|
127
|
-
{ from: "request", to: "query" },
|
128
|
-
{ from: "disconnect", to: "close" }
|
129
|
-
];
|
130
|
-
|
131
|
-
function applyAliases(obj) {
|
132
|
-
apiAliases.forEach(function(alias) {
|
133
|
-
obj[alias.from] = obj[alias.to];
|
134
|
-
});
|
135
|
-
}
|
136
|
-
|
137
|
-
|
138
|
-
function parseBool(b) { return !!b }
|
139
|
-
|
140
|
-
function parseOptions(opts, globalOpts) {
|
141
|
-
if(!opts) opts = {};
|
142
|
-
// Construct new options object by reducing the options found in the definitions object
|
143
|
-
var result = Object.keys(optionDefinition).reduce(function(o, option) {
|
144
|
-
var definition = optionDefinition[option];
|
145
|
-
var given = opts[option];
|
146
|
-
var parsed = globalOpts ? globalOpts[option] : undefined;
|
147
|
-
if(given === undefined) {
|
148
|
-
if (parsed === undefined && definition.dflt === undefined) {
|
149
|
-
// only fail if we are not constructing the global opts, since global opts
|
150
|
-
// might miss required options, which then have to be filled in by local options
|
151
|
-
if(!globalOpts) return o;
|
152
|
-
throw new Error('Required option "' + option + '" not found..');
|
153
|
-
}
|
154
|
-
o[option] = parsed !== undefined ? parsed : definition.dflt;
|
155
|
-
return o;
|
156
|
-
}
|
157
|
-
if(typeof(given) != definition.type) {
|
158
|
-
throw new Error(
|
159
|
-
'Option "' + option + '" has the wrong type. ' +
|
160
|
-
'Expected: "' + definition.type + '"' +
|
161
|
-
'Given: "' + typeof(given) + '"'
|
162
|
-
);
|
163
|
-
}
|
164
|
-
o[option] = definition.transform ? definition.transform(given) : given;
|
165
|
-
return o;
|
166
|
-
}, {});
|
167
|
-
|
168
|
-
// report any unrecognized options if debug mode is set on the new options object
|
169
|
-
if(result.warnings) {
|
170
|
-
Object.keys(opts).forEach(function(option) {
|
171
|
-
if(result[option] === undefined) {
|
172
|
-
result.warningFn(result.logger, 'Unrecognized option "' + option + '"');
|
173
|
-
}
|
174
|
-
});
|
175
|
-
}
|
176
|
-
|
177
|
-
return result;
|
178
|
-
}
|
179
|
-
|
180
|
-
function prettyResult(result) {
|
181
|
-
// Do an in-place replacement of the entries of the result.data array
|
182
|
-
result.data && result.data.forEach(function(tuple, i) {
|
183
|
-
var tupleObj = {};
|
184
|
-
tuple.forEach(function(val, j) {
|
185
|
-
tupleObj[result.structure[j].column] = val;
|
186
|
-
});
|
187
|
-
result.data[i] = tupleObj;
|
188
|
-
});
|
189
|
-
}
|
190
|
-
|
191
|
-
function promiseFnWrapper(thisArg, fn, returnVal) {
|
192
|
-
return function() {
|
193
|
-
var args = Array.prototype.slice.call(arguments);
|
194
|
-
var callback = (typeof(args[args.length - 1]) == 'function') ? args.pop() : null;
|
195
|
-
var promise = fn.apply(thisArg, args);
|
196
|
-
if (callback) {
|
197
|
-
promise.then(function (result) {
|
198
|
-
callback(null, result);
|
199
|
-
}, function (err) {
|
200
|
-
callback(err);
|
201
|
-
});
|
202
|
-
}
|
203
|
-
return returnVal;
|
204
|
-
};
|
205
|
-
}
|
206
|
-
|
207
|
-
|
208
|
-
module.exports = function(d) {
|
209
|
-
var globalOpts = parseOptions(d);
|
210
|
-
|
211
|
-
function MonetDBConnection(d) {
|
212
|
-
var self = this;
|
213
|
-
|
214
|
-
// private vars and functions
|
215
|
-
var _options = parseOptions(d, globalOpts);
|
216
|
-
|
217
|
-
// public vars and functions
|
218
|
-
self.mapiConnection = new MapiConnection(_options);
|
219
|
-
|
220
|
-
self.autoCommit = _options.autoCommit;
|
221
|
-
self.setAutocommit = function(autocommit) {
|
222
|
-
if(typeof autocommit !== 'boolean') {
|
223
|
-
throw new TypeError('expected boolean argument');
|
224
|
-
}
|
225
|
-
self.autoCommit = autocommit;
|
226
|
-
const mode = Boolean(autocommit) ? 1 : 0;
|
227
|
-
const msg = `Xauto_commit ${mode}`;
|
228
|
-
self.mapiConnection.request(msg);
|
229
|
-
}
|
230
|
-
|
231
|
-
self.query = function(query) {
|
232
|
-
var params = [];
|
233
|
-
var pretty = _options.prettyResult;
|
234
|
-
for (var i=0; i<arguments.length; ++i) {
|
235
|
-
var arg = arguments[i];
|
236
|
-
if (Array.isArray(arg)) {
|
237
|
-
params = arg;
|
238
|
-
} else if((typeof arg) == 'boolean') {
|
239
|
-
pretty = arg;
|
240
|
-
}
|
241
|
-
}
|
242
|
-
|
243
|
-
if (params.length) {
|
244
|
-
var releaseFun = null;
|
245
|
-
return self.prepare(query, false).then(function(prepResult) {
|
246
|
-
releaseFun = prepResult.release;
|
247
|
-
return prepResult.exec(params);
|
248
|
-
}).then(function(result) {
|
249
|
-
pretty && prettyResult(result);
|
250
|
-
releaseFun();
|
251
|
-
return result;
|
252
|
-
});
|
253
|
-
}
|
254
|
-
|
255
|
-
return self.mapiConnection.request(utils.packQuery(query)).then(function(result) {
|
256
|
-
pretty && prettyResult(result);
|
257
|
-
return result;
|
258
|
-
});
|
259
|
-
};
|
260
|
-
|
261
|
-
self.querystream = function(query) {
|
262
|
-
return self.mapiConnection.request(utils.packQuery(query),true);
|
263
|
-
}
|
264
|
-
self.prepare = function(query, prettyResult) {
|
265
|
-
if (query.toUpperCase().trim().substring(0,7) != 'PREPARE')
|
266
|
-
query = 'PREPARE ' + query;
|
267
|
-
return self.mapiConnection.request(utils.packQuery(query)).then(function(result) {
|
268
|
-
function execfun(bindparams) {
|
269
|
-
var quoted = bindparams.map(function (param, paramIndex) {
|
270
|
-
if (param === null) {
|
271
|
-
return 'NULL';
|
272
|
-
}
|
273
|
-
var type = typeof param;
|
274
|
-
var s;
|
275
|
-
switch (type) {
|
276
|
-
case 'boolean':
|
277
|
-
case 'number':
|
278
|
-
s = '' + param;
|
279
|
-
break;
|
280
|
-
case 'string':
|
281
|
-
/* escape single quotes except if they are already escaped */
|
282
|
-
s = "'" + param.replace(/([^\\])'/g, "$1\\'") + "'";
|
283
|
-
break;
|
284
|
-
case 'object':
|
285
|
-
s = "json '" + JSON.stringify(param).replace(/([^\\])'/g, "$1\\'") + "'";
|
286
|
-
break;
|
287
|
-
default:
|
288
|
-
s = param;
|
289
|
-
break;
|
290
|
-
}
|
291
|
-
var colData = result.data[result.rows - bindparams.length + paramIndex];
|
292
|
-
if (colData) {
|
293
|
-
var toCheck = ['timestamp', 'timestamptz', 'date', 'uuid'];
|
294
|
-
var i = toCheck.indexOf(colData[0]);
|
295
|
-
if (i >= 0) {
|
296
|
-
s = toCheck[i] + ' ' + s;
|
297
|
-
}
|
298
|
-
}
|
299
|
-
return s;
|
300
|
-
}).join(', ');
|
301
|
-
var execquery = 'EXEC ' + result.queryid + '(' + quoted + ')';
|
302
|
-
return self.query(execquery, prettyResult);
|
303
|
-
}
|
304
|
-
|
305
|
-
function releasefun() {
|
306
|
-
self.mapiConnection.request('Xrelease ' + result.queryid);
|
307
|
-
}
|
308
|
-
|
309
|
-
return {'prepare': result, 'exec': execfun, 'release': releasefun};
|
310
|
-
});
|
311
|
-
};
|
312
|
-
|
313
|
-
self.env = function() {
|
314
|
-
return self.mapiConnection.request(utils.packQuery('SELECT * FROM env()')).then(function(result) {
|
315
|
-
if(!result.rows || !result.data) throw new Error('Could not fetch server environment');
|
316
|
-
return result.data.reduce(function(o, arr) {
|
317
|
-
o[arr[0]] = arr[1];
|
318
|
-
return o;
|
319
|
-
}, {});
|
320
|
-
});
|
321
|
-
};
|
322
|
-
|
323
|
-
self.option = function(option, val) {
|
324
|
-
var def = optionDefinition[option];
|
325
|
-
if(!def) throw new Error('Option "' + option + '" does not exist');
|
326
|
-
if(arguments.length == 1) return _options[option];
|
327
|
-
if(!def.changeable) throw new Error('Option "' + option + '" can not be changed. Please set this option on a new connection.');
|
328
|
-
if(typeof(val) != def.type) throw new Error('Option "' + option + '" should be of type "' + def.type + '"');
|
329
|
-
_options[option] = def.transform ? def.transform(val) : val;
|
330
|
-
};
|
331
|
-
|
332
|
-
// proxy some methods
|
333
|
-
self.connect = self.mapiConnection.connect;
|
334
|
-
self.getState = self.mapiConnection.getState;
|
335
|
-
self.close = async () => {
|
336
|
-
if (self.autoCommit === false) {
|
337
|
-
try {
|
338
|
-
const q = utils.packQuery("ROLLBACK");
|
339
|
-
await self.mapiConnection.request(q);
|
340
|
-
} catch (err) {
|
341
|
-
console.error(err);
|
342
|
-
}
|
343
|
-
|
344
|
-
}
|
345
|
-
self.mapiConnection.close();
|
346
|
-
}
|
347
|
-
self.end = self.mapiConnection.end;
|
348
|
-
self.destroy = self.mapiConnection.destroy;
|
349
|
-
|
350
|
-
applyAliases(self);
|
351
|
-
|
352
|
-
self.getCallbackWrapper = function() {
|
353
|
-
var wrapper = {
|
354
|
-
option: self.option,
|
355
|
-
getState: self.getState,
|
356
|
-
destroy: self.destroy
|
357
|
-
};
|
358
|
-
|
359
|
-
// wrap connect, query and env
|
360
|
-
["connect", "query", "env", "close"].forEach(function(method) {
|
361
|
-
wrapper[method] = promiseFnWrapper(self, self[method], wrapper);
|
362
|
-
});
|
363
|
-
|
364
|
-
// wrap prepare, which is somewhat more complicated, since it needs to return callback based exec and release fns
|
365
|
-
wrapper.prepare = function() {
|
366
|
-
var args = Array.prototype.slice.call(arguments);
|
367
|
-
var callback = (typeof(args[args.length - 1]) == 'function') ? args.pop() : null;
|
368
|
-
if(!callback) return wrapper; // if no callback is provided, what is the point in preparing something?
|
369
|
-
var promise = self.prepare.apply(self, args);
|
370
|
-
promise.then(function (prepResult) {
|
371
|
-
prepResult.exec = promiseFnWrapper(self, prepResult.exec);
|
372
|
-
callback(null, prepResult);
|
373
|
-
}, function (err) {
|
374
|
-
callback(err);
|
375
|
-
});
|
376
|
-
return wrapper;
|
377
|
-
};
|
378
|
-
|
379
|
-
applyAliases(wrapper);
|
380
|
-
|
381
|
-
return wrapper;
|
382
|
-
};
|
383
|
-
}
|
384
|
-
return MonetDBConnection;
|
385
|
-
};
|
package/src/utils.js
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Author: Robin Cijvat <robin.cijvat@monetdbsolutions.com>
|
3
|
-
*/
|
4
|
-
|
5
|
-
'use strict';
|
6
|
-
|
7
|
-
module.exports.debug = function(logger, msg) {
|
8
|
-
logger('DEBUG ' + msg);
|
9
|
-
};
|
10
|
-
|
11
|
-
module.exports.warning = function(logger, msg) {
|
12
|
-
logger('WARNING ' + msg);
|
13
|
-
};
|
14
|
-
|
15
|
-
module.exports.debugRequest = function(logger, request, error, result) {
|
16
|
-
logger(request);
|
17
|
-
error && logger(error);
|
18
|
-
result && result.rows && result.cols && logger("qid[" + result.queryid + "] " + result.rows + " rows, " + result.cols + " cols");
|
19
|
-
};
|
20
|
-
|
21
|
-
module.exports.debugMapi = function(logger, type, msg) {
|
22
|
-
logger(type + ": " + msg);
|
23
|
-
};
|
24
|
-
|
25
|
-
module.exports.packQuery = function(msg) {
|
26
|
-
return 's' + msg + ';';
|
27
|
-
};
|
package/test/common.js
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
|
2
|
-
var Q = require("q");
|
3
|
-
const mdb = require("../index.js");
|
4
|
-
|
5
|
-
let seed = 1;
|
6
|
-
|
7
|
-
module.exports = {
|
8
|
-
getMDB(opts = {warnings: false, dbname: "test"}) {
|
9
|
-
return mdb(opts);
|
10
|
-
},
|
11
|
-
|
12
|
-
notSoRandom() {
|
13
|
-
var x = Math.sin(seed++) * 10000;
|
14
|
-
return x - Math.floor(x);
|
15
|
-
},
|
16
|
-
|
17
|
-
shouldHaveValidResult(query, nrRows, nrCols, colNames) {
|
18
|
-
var colObj = colNames.reduce(function(o, v, i) {
|
19
|
-
o[v] = i;
|
20
|
-
return o;
|
21
|
-
}, {});
|
22
|
-
return Q.all([
|
23
|
-
query.should.not.be.rejected,
|
24
|
-
query.should.eventually.have.all.keys(["rows", "cols", "data", "col", "structure", "queryid", "type"]),
|
25
|
-
query.should.eventually.have.property("rows", nrRows),
|
26
|
-
query.should.eventually.have.property("cols", nrCols),
|
27
|
-
query.should.eventually.have.property("col")
|
28
|
-
.that.is.an("object")
|
29
|
-
.that.deep.equals(colObj),
|
30
|
-
query.should.eventually.have.property("queryid")
|
31
|
-
.that.is.a("number"),
|
32
|
-
query.should.eventually.have.property("type")
|
33
|
-
.that.equals("table"),
|
34
|
-
query.should.eventually.have.property("structure")
|
35
|
-
.that.is.an("array")
|
36
|
-
.with.length(nrCols)
|
37
|
-
.and.has.property("0")
|
38
|
-
.that.has.all.keys(["table", "column", "type", "typelen", "index"])
|
39
|
-
]).then(function() {
|
40
|
-
return query;
|
41
|
-
});
|
42
|
-
}
|
43
|
-
};
|
44
|
-
|
45
|
-
|
package/test/install-monetdb.sh
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
#!/usr/bin/env bash
|
2
|
-
|
3
|
-
add-apt-repository "http://dev.monetdb.org/downloads/deb/ monetdb"
|
4
|
-
|
5
|
-
wget --output-document=- https://www.monetdb.org/downloads/MonetDB-GPG-KEY | apt-key add -
|
6
|
-
|
7
|
-
apt-get update
|
8
|
-
|
9
|
-
apt-get install monetdb5-sql monetdb-client
|
10
|
-
|
11
|
-
printf "user=monetdb\npassword=monetdb\n" > ~/.monetdb
|
package/test/monetdb_stream.js
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
|
2
|
-
const { getMDB } = require('./common');
|
3
|
-
|
4
|
-
|
5
|
-
describe('Query stream', () => {
|
6
|
-
const MDB = getMDB();
|
7
|
-
|
8
|
-
it('should call callbacks', async () => {
|
9
|
-
const conn = new MDB();
|
10
|
-
const sql = 'select * from columns';
|
11
|
-
|
12
|
-
await conn.connect();
|
13
|
-
|
14
|
-
const { header: hdrEventCount, data: dataEventCnt, end: endEventCount } = await test_callbacks(conn, sql);
|
15
|
-
hdrEventCount.should.equal(1);
|
16
|
-
(dataEventCnt > 0).should.be.true;
|
17
|
-
endEventCount.should.equal(1);
|
18
|
-
conn.close();
|
19
|
-
});
|
20
|
-
|
21
|
-
it('should produce result', async () => {
|
22
|
-
const sql = 'SELECT table_type_id,table_type_name FROM table_types where table_type_id in (0,1,3,4,5)';
|
23
|
-
const conn = new MDB();
|
24
|
-
await conn.connect();
|
25
|
-
|
26
|
-
const res = await test_result(conn, sql);
|
27
|
-
Boolean(res).should.be.true;
|
28
|
-
conn.close();
|
29
|
-
});
|
30
|
-
|
31
|
-
it('should produce equal results', async() => {
|
32
|
-
const sql = 'select * from columns';
|
33
|
-
const conn = new MDB();
|
34
|
-
await conn.connect();
|
35
|
-
const left = await conn.query(sql);
|
36
|
-
const right = await test_result(conn, sql);
|
37
|
-
left.data.toString().should.equal(right.data.toString());
|
38
|
-
});
|
39
|
-
|
40
|
-
|
41
|
-
});
|
42
|
-
|
43
|
-
|
44
|
-
function test_callbacks (conn, sql) {
|
45
|
-
const lookup = {
|
46
|
-
header: 0,
|
47
|
-
data: 0,
|
48
|
-
end: 0
|
49
|
-
};
|
50
|
-
return new Promise((resolve, reject) => {
|
51
|
-
conn.querystream(sql)
|
52
|
-
.on('error', (err) => {
|
53
|
-
return reject(err);
|
54
|
-
})
|
55
|
-
.on('header', (header) => {
|
56
|
-
lookup.header +=1;
|
57
|
-
})
|
58
|
-
.on('data', (data) => {
|
59
|
-
lookup.data +=1;
|
60
|
-
})
|
61
|
-
.on('end', () => {
|
62
|
-
lookup.end +=1;
|
63
|
-
resolve(lookup);
|
64
|
-
});
|
65
|
-
});
|
66
|
-
}
|
67
|
-
|
68
|
-
|
69
|
-
function test_result(conn, sql){
|
70
|
-
var result;
|
71
|
-
return new Promise(function(resolve, reject) {
|
72
|
-
//we simulate the same structure produced by buffer response (/query)
|
73
|
-
var query = conn.querystream(sql);
|
74
|
-
var firstchunck = true;
|
75
|
-
var error_flag = false;
|
76
|
-
query
|
77
|
-
.on('error', function(err) {
|
78
|
-
error_flag = true;
|
79
|
-
reject(err);
|
80
|
-
// Handle error, an 'end' event will be emitted after this as well
|
81
|
-
})
|
82
|
-
.on('header', function(header) {
|
83
|
-
// the field packets for the rows to follow
|
84
|
-
var strheader = JSON.stringify(header);
|
85
|
-
result = strheader.substr(0,strheader.length-1);
|
86
|
-
})
|
87
|
-
.on('data', function(rows) {
|
88
|
-
var strrows = JSON.stringify(rows);
|
89
|
-
if (firstchunck) {
|
90
|
-
strrows = ',"data":' + strrows.substr(0,strrows.length-1);
|
91
|
-
} else {
|
92
|
-
strrows = ',' + strrows.substr(1,strrows.length-2);
|
93
|
-
}
|
94
|
-
firstchunck = false;
|
95
|
-
result += strrows;
|
96
|
-
})
|
97
|
-
.on('end', function() {
|
98
|
-
if (!error_flag) {
|
99
|
-
// all rows have been received withour error
|
100
|
-
result += ']}';
|
101
|
-
var res = JSON.parse(result);
|
102
|
-
resolve(res);
|
103
|
-
}
|
104
|
-
});
|
105
|
-
});
|
106
|
-
}
|
package/test/start-monetdb.sh
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
#!/usr/bin/env bash
|
2
|
-
|
3
|
-
monetdbd create ./dbfarm
|
4
|
-
monetdbd start ./dbfarm
|
5
|
-
|
6
|
-
sleep 10
|
7
|
-
|
8
|
-
monetdb create test
|
9
|
-
monetdb release test
|
10
|
-
monetdb start test
|
11
|
-
|
12
|
-
|
13
|
-
function test_monetdb_connection() {
|
14
|
-
mclient -d test -s 'SELECT 1' &> /dev/null
|
15
|
-
local status=$?
|
16
|
-
if [ $status -ne 0 ]; then
|
17
|
-
return 0
|
18
|
-
fi
|
19
|
-
return 1
|
20
|
-
}
|
21
|
-
|
22
|
-
for i in {30..0}; do
|
23
|
-
echo 'Testing MonetDB connection ' $i
|
24
|
-
if test_monetdb_connection ; then
|
25
|
-
echo 'Waiting for MonetDB to start...'
|
26
|
-
sleep 1
|
27
|
-
else
|
28
|
-
echo 'MonetDB is running'
|
29
|
-
break
|
30
|
-
fi
|
31
|
-
done
|
32
|
-
if [ "$i" = 0 ]; then
|
33
|
-
echo >&2 'MonetDB startup failed'
|
34
|
-
exit 1
|
35
|
-
fi
|
36
|
-
|
37
|
-
|
38
|
-
|