Skip to content
This repository has been archived by the owner on Feb 22, 2019. It is now read-only.

Commit

Permalink
added better cql creation and parsing [ closes #36, closes #39 ]
Browse files Browse the repository at this point in the history
  • Loading branch information
devdazed committed Apr 20, 2012
1 parent f9bdb33 commit bd676d4
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 26 deletions.
78 changes: 65 additions & 13 deletions lib/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,76 @@ function createError(err){
}

/**
* Escapes a string as required by CQL
* Formats CQL properly, paradigm borrowed from node-mysql:
* https://github.com/felixge/node-mysql/blob/master/lib/client.js#L145-199
*
* @param {String} str
* @private
* @memberOf Connection
* @returns {String} The sanitized string
*/
function cqlEscape(str){
if(str instanceof Buffer){
return str.toString('hex');
} else {
return str.toString().replace(/\'/img, '\'\'');
function formatCQL(cql, params){
//replace a %% with a % to maintain backward compatibility with util.format
cql = cql.replace(/%%/, '%');

//remove existing quotes around parameters in case the user has already wrapped them
cql = cql.replace(/'(\?|%[sjd])'/g, '$1');

//escape the params and format the CQL string
cql = cql.replace(/\?|%[sjd]/g, function() {
if (params.length === 0) {
throw createError(new Error('Too Few Parameters Given'));
}

return escapeCQL(params.shift());
});

if (params.length) {
throw createError(new Error('Too Many Parameters Given'));
}

return cql;
}

/**
* Escapes CQL, adapted from node-mysql
* @param {String} val The value to be escaped
*/
function escapeCQL(val) {
if (val === undefined || val === null) {
return 'NULL';
}

if(val instanceof Buffer){
return val.toString('hex');
}

if(typeof val === 'boolean' || typeof val === 'number'){
return val.toString();
}

if (Array.isArray(val)) {
var sanitized = val.map( function( v ) { return escapeCQL( v ); } );
return "'" + sanitized.join( "','" ) + "'";
}

if (typeof val === 'object') {
val = (typeof val.toISOString === 'function') ? val.toISOString() : val.toString();
}

val = val.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) {
switch(s) {
case "\0": return "\\0";
case "\n": return "\\n";
case "\r": return "\\r";
case "\b": return "\\b";
case "\t": return "\\t";
case "\x1a": return "\\Z";
case "'": return "''";
default: return "\\"+s;
}
});
return "'"+val+"'";
}

/**
Expand Down Expand Up @@ -365,13 +423,7 @@ Connection.prototype.cql = function(cmd, args, options, callback){
var cql, escaped = [], self = this;

if(args){
var i = 0;
for(; i < args.length; i += 1){
escaped.push(cqlEscape(args[i]));
}

escaped.unshift(cmd.replace(/\?/g, '%s'));
cql = new Buffer(util.format.apply(this, escaped));
cql = new Buffer(formatCQL(cmd, args));
} else {
cql = new Buffer(cmd);
}
Expand Down
46 changes: 33 additions & 13 deletions test/cql2.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,48 +23,48 @@ module.exports = {
connect();
});
},

'test cql create keyspace':function(test, assert){
conn.cql(config['create_ks#cql'], function(err, res){
assert.ifError(err);
assert.ok(res === undefined);
test.finish();
});
},

'test cql use keyspace':function(test, assert){
conn.cql(config['use#cql'], function(err, res){
assert.ifError(err);
assert.ok(res === undefined);
test.finish();
});
},

'test cql create column family':function(test, assert){
conn.cql(config['create_cf#cql'], function(err, res){
assert.ifError(err);
assert.ok(res === undefined);
test.finish();
});
},

'test cql update':function(test, assert){
conn.cql(config['update#cql'], function(err, res){
assert.ifError(err);
assert.ok(res === undefined);
test.finish();
});
},

'test cql update with no callback':function(test, assert){
conn.cql(config['update#cql']);

//just wait to see if anything bad happens
setTimeout(function(){
test.finish();
}, 100);
},

'test cql select':function(test, assert){
conn.cql(config['select#cql'], function(err, res){
assert.ifError(err);
Expand Down Expand Up @@ -97,7 +97,7 @@ module.exports = {
test.finish();
});
},

'test cql error':function(test, assert){
conn.cql(config['error#cql'], function(err, res){
assert.ok(err instanceof Error);
Expand All @@ -107,7 +107,7 @@ module.exports = {
test.finish();
});
},

'test cql count with gzip':function(test, assert){
conn.cql(config['count#cql'], {gzip:true}, function(err, res){
assert.ifError(err);
Expand All @@ -117,7 +117,7 @@ module.exports = {
test.finish();
});
},

'test cql delete':function(test, assert){
conn.cql(config['delete#cql'], function(err, res){
assert.ifError(err);
Expand All @@ -142,17 +142,37 @@ module.exports = {
test.finish();
});
},

'test cql drop keyspace':function(test, assert){
conn.cql(config['drop_ks#cql'], function(err, res){
assert.ifError(err);
assert.ok(res === undefined);
test.finish();
});
},


'test too many cql params':function(test, assert){
assert.throws(function(){
conn.cql(config['select2#cql'], [1,2,3,4,5,6]);
}, function(err){
return err.message === 'Too Many Parameters Given';
});

test.finish();
},

'test too few cql params':function(test, assert){
assert.throws(function(){
conn.cql(config['select2#cql'], []);
}, function(err){
return err.message === 'Too Few Parameters Given';
});

test.finish();
},

'tearDown':function(test, assert){
conn.close();
test.finish();
}
};
};

0 comments on commit bd676d4

Please sign in to comment.