Changeset: eca52f8c4bd9 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=eca52f8c4bd9
Modified Files:
        clients/nodejs/monetdb/README
        clients/nodejs/monetdb/mapiclient.js
Branch: Oct2014
Log Message:

Node.JS connector: Error handling


diffs (261 lines):

diff --git a/clients/nodejs/monetdb/README b/clients/nodejs/monetdb/README
--- a/clients/nodejs/monetdb/README
+++ b/clients/nodejs/monetdb/README
@@ -2,10 +2,10 @@ This package connects node.js and MonetD
 
 Example usage:
 
-var conn = require('monetdb').connect({'dbname':'mydb'} , function() {
-       console.log('connected');
+var conn = require('monetdb').connect({'dbname':'mydb'} , function(response) {
+       if (response.success) console.log('connected');
 });
 
 conn.request('SELECT 1', function(response) {
-       console.log(response.success);
+       console.log(response);
 });
\ No newline at end of file
diff --git a/clients/nodejs/monetdb/mapiclient.js 
b/clients/nodejs/monetdb/mapiclient.js
--- a/clients/nodejs/monetdb/mapiclient.js
+++ b/clients/nodejs/monetdb/mapiclient.js
@@ -8,6 +8,7 @@ function MonetDBConnection(options, conn
        this.read_final = false;
        this.read_str = '';
        this.read_callback = undefined;
+       this.conn_callback = conncallback;
        this.mapi_blocksize = 8192;
 
        this.queryqueue = [];
@@ -22,8 +23,8 @@ function MonetDBConnection(options, conn
                thizz.state = 'disconnected';
        });
        this.socket.on('error', function(x) {
-               // TODO: how should we handle this? 
-               console.log(x);
+               if (conncallback != undefined)
+                       conncallback({'success':false, 'message':x.toString()});
        });
        /* some setup */
        this.request('Xreply_size -1', undefined, true);
@@ -36,8 +37,8 @@ function MonetDBConnection(options, conn
                 });
        });
        this.request('SELECT 42', function(x) {
-               if (conncallback != undefined)
-                       conncallback();
+               if (this.conn_callback != undefined)
+                       this.conn_callback({'success':true, 'message':'ok'});
        });
 }
 
@@ -49,6 +50,65 @@ MonetDBConnection.prototype.query = func
        this.queryqueue.push({'message' : message , 'callback' : callback})
 }
 
+
+MonetDBConnection.prototype.handleMessage = function(message) {
+       if (this.options.debug)
+               console.log('RX ['+this.state+']: '+message);
+
+       /* prompt, good */
+       if (message == '') {
+               this.state = 'ready';
+               this.nextOp();
+               return;
+       }
+
+       /* monetdbd redirect, ignore. We will get another challenge soon */
+       if (message.charAt(0) == '^') {
+               return;
+       }
+
+       if (this.state == 'connected') {
+               /* error message during authentication? */
+               if (message.charAt(0) == '!') {
+                       message = 'Error: 
'+message.substring(1,message.length-1);
+                       if (this.conn_callback != undefined)
+                               this.conn_callback({'success':false, 
'message':message});
+                       return;
+               }
+
+               // means we get the challenge from the server
+               var authch = message.split(':');
+               var salt   = authch[0];
+               var dbname = authch[1];
+               var pwhash = __sha512(__sha512(this.options.password) + salt)
+               var response = 'LIT:' + this.options.user + ':{SHA512}' + 
pwhash + ':' +
+                       this.options.language + ':' + this.options.dbname + ':';
+               this.sendMessage(response);
+               return;
+       }
+
+       var response = {};
+
+       /* error message */
+       if (message.charAt(0) == '!') {
+               response.success = false;
+               response.error = message.substring(1);
+       }
+
+       /* query result */
+       if (message.charAt(0) == '&') {
+               response = _parseresponse(message);
+               response.success = true;
+       }
+
+       if (this.read_callback != undefined) {
+               this.read_callback(response);
+               this.read_callback = undefined;
+       }
+       this.nextOp();  
+}
+
+
 MonetDBConnection.prototype.nextOp = function() {
        if (this.queryqueue.length < 1) {
                return;
@@ -119,59 +179,10 @@ MonetDBConnection.prototype.sendMessage 
 
 /* In theory, the server tells us which hashes he likes. 
    In practice, we know he always likes sha512 , so... */
-function sha512(str) {
+function __sha512(str) {
        return crypto.createHash('sha512').update(str).digest('hex');
 }
 
-MonetDBConnection.prototype.handleMessage = function(message) {
-       if (this.options.debug)
-               console.log('RX ['+this.state+']: '+message);
-
-       /* prompt, good */
-       if (message == '') {
-               this.state = 'ready';
-               this.nextOp();
-               return;
-       }
-
-       /* monetdbd redirect, ignore. We will get another challenge soon */
-       if (message.charAt(0) == '^') {
-               return;
-       }
-
-       if (this.state == 'connected') {
-               // means we get the challenge from the server
-               var authch = message.split(':');
-               var salt   = authch[0];
-               var dbname = authch[1];
-               var pwhash = sha512(sha512(this.options.password) + salt)
-               var response = 'LIT:' + this.options.user + ':{SHA512}' + 
pwhash + ':' +
-                       this.options.language + ':' + this.options.dbname + ':';
-               this.sendMessage(response);
-               return;
-       }
-
-       var response = {};
-
-       /* error message */
-       if (message.charAt(0) == '!') {
-               response.success = false;
-               response.error = message.substring(1);
-       }
-
-       /* query result */
-       if (message.charAt(0) == '&') {
-               response = _parseresponse(message);
-               response.success = true;
-       }
-
-       if (this.read_callback != undefined) {
-               this.read_callback(response);
-               this.read_callback = undefined;
-       }
-       this.nextOp();
-       
-}
 
 function _parsetuples(names, types, lines) {
        var state = 'INCRAP';
@@ -185,7 +196,7 @@ function _parsetuples(names, types, line
                var cCol = 0;
 
                /* mostly adapted from clients/R/MonetDB.R/src/mapisplit.c */
-               for (var curPos = tokenStart; curPos<line.length-1; curPos++) {
+               for (var curPos = tokenStart; curPos < line.length - 1; 
curPos++) {
                        var chr = line.charAt(curPos);
                        switch (state) {
                        case 'INCRAP':
@@ -278,7 +289,7 @@ function _parseresponse(msg) {
                var type_lengths = _hdrline(lines[4]);
 
                resp.structure = [];
-               for (var i=0;i<table_names.length;i++) {
+               for (var i = 0; i < table_names.length; i++) {
                        resp.structure.push({
                                table : table_names[i],
                                column : column_names[i],
@@ -294,30 +305,50 @@ function _parseresponse(msg) {
 MonetDBConnection.prototype.close = function() {
        var thizz = this;
        /* kills the connection after the query has been processed (will also 
wait for all others) */
-       this.request('SELECT 1', function(x) {
+       this.request('SELECT 42', function(x) {
                thizz.socket.destroy();
        });
 }
 
-exports.connect = function() {
+exports.connect = exports.open = function() {
   return new MonetDBConnection(getConnectArgs(arguments[0]), arguments[1]);
 }
 
-function isObject(obj) {
-       return typeof obj !== 'undefined';
+function __check_arg(options, argname, type, dflt) {
+       var argval = options[argname];
+       options[argname] = dflt;
+       
+       if (typeof argval === 'undefined') {
+               return;
+       }
+       if (typeof argval !== type) {
+               console.warn('parameter ' + argname + ' should be ' + type + ' 
but is ' + typeof argval);
+               return;
+       }
+
+       if (type == 'string') {
+               if (typeof argval != 'string') {
+                       return;
+               }
+               argval = argval.trim();
+               if (argval == '') {
+                       console.warn('parameter ' + argname + ' is empty');
+                       return;
+               }
+               options[argname] = argval;
+       } else {
+               options[argname] = argval;
+       }
 }
 
 function getConnectArgs(options) {
-
-  if (!isObject(options.dbname))   options.dbname   = 'demo';
-  if (!isObject(options.user))     options.user     = 'monetdb';
-  if (!isObject(options.password)) options.password = 'monetdb';
-  if (!isObject(options.host))     options.host     = 'localhost';
-  if (!isObject(options.port))     options.port     = 50000;
-  if (!isObject(options.language)) options.language = 'sql';
-  if (!isObject(options.debug))    options.debug    = false;
-  // TODO: check options for type and whether they make sense
-
+       __check_arg(options, 'dbname'  , 'string' , 'demo');
+       __check_arg(options, 'user'    , 'string' , 'monetdb');
+       __check_arg(options, 'password', 'string' , 'monetdb');
+       __check_arg(options, 'host'    , 'string' , 'localhost');
+       __check_arg(options, 'port'    , 'int'    , 50000);
+       __check_arg(options, 'language', 'string' , 'sql');
+       __check_arg(options, 'debug'   , 'boolean', false);
   return options;
 }
 
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to