monetdb 1.3.3 → 2.0.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 (47) hide show
  1. package/.github/workflows/Linux.yml +45 -0
  2. package/.github/workflows/docs.yml +79 -0
  3. package/.github/workflows/macos.yml +43 -0
  4. package/.github/workflows/monetdb-versions.yml +43 -0
  5. package/README.md +43 -512
  6. package/docs/components/alert.tsx +10 -0
  7. package/docs/components/info.tsx +6 -0
  8. package/docs/next.config.js +24 -0
  9. package/docs/package-lock.json +5069 -0
  10. package/docs/package.json +22 -0
  11. package/docs/pages/_app.js +9 -0
  12. package/docs/pages/_meta.json +16 -0
  13. package/docs/pages/apis/_meta.json +4 -0
  14. package/docs/pages/apis/connection.mdx +60 -0
  15. package/docs/pages/apis/result.mdx +39 -0
  16. package/docs/pages/index.mdx +27 -0
  17. package/docs/theme.config.js +35 -0
  18. package/docs/v1/README.md +532 -0
  19. package/package.json +17 -21
  20. package/src/PrepareStatement.ts +37 -0
  21. package/src/connection.ts +125 -0
  22. package/src/defaults.ts +13 -0
  23. package/src/file-transfer.ts +173 -0
  24. package/src/index.ts +3 -0
  25. package/src/mapi.ts +1016 -0
  26. package/src/monetize.ts +67 -0
  27. package/test/connection.ts +43 -0
  28. package/test/exec-queries.ts +100 -0
  29. package/test/filetransfer.ts +94 -0
  30. package/test/prepare-statement.ts +27 -0
  31. package/test/query-stream.ts +41 -0
  32. package/test/tmp/.gitignore +4 -0
  33. package/tsconfig.json +24 -0
  34. package/.travis.yml +0 -11
  35. package/index.js +0 -5
  36. package/src/mapi-connection.js +0 -784
  37. package/src/monetdb-connection.js +0 -385
  38. package/src/utils.js +0 -27
  39. package/test/common.js +0 -45
  40. package/test/install-monetdb.sh +0 -11
  41. package/test/monetdb_stream.js +0 -106
  42. package/test/start-monetdb.sh +0 -38
  43. package/test/test.js +0 -908
  44. package/test/test_connection.js +0 -290
  45. /package/docs/{README.v0.md → v0/README.v0.md} +0 -0
  46. /package/docs/{MapiConnection.md → v1/MapiConnection.md} +0 -0
  47. /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
-
@@ -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
@@ -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
- }
@@ -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
-