Skip to content

Updates for the latest version of node #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .cupboard
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[project]
name = dbslayer
[commands]
publish = git add ., git commit -m "$@", git push origin master
ignore = echo $@ >> .gitignore
119 changes: 84 additions & 35 deletions README.md
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
node.dbslayer.js
=================

node.dbslayer.js is a very basic and easy-to-use library to connect to a DBSlayer server, which effectively provides non-blocking and scalable MySQL support for Node.JS.
node.dbslayer.js is a very basic and easy-to-use library to connect to a DBSlayer server, which effectively provides non-blocking and scalable MySQL support for Node.JS.

DBSlayer benefits include:

Expand All @@ -12,40 +12,80 @@ DBSlayer benefits include:
Requirements
------------

* [Node.js](http://nodejs.org/) (tested with v0.1.21)
* [Node.js](http://nodejs.org/) (tested with v0.1.90)
* [DBSlayer](http://code.nytimes.com/projects/dbslayer/) (tested with beta-12)

How to Install ![New!](http://i.imgur.com/XSqxQs.jpg)
--------------

From your npm equipped command line:

npm install dbslayer

How to Use
----------

From your node.js script, require the `dbslayer` package

var db = require('dbslayer');
var db = require('dbslayer');

Initialize a connection

var connection = db.Server('localhost', 9090);
var connection = db.Server('localhost', 9090);

and then perform a query:

connection.query("SELECT * FROM table");

To be truly non-blocking, `Server::fetch` has to return a promise and not the result immediately. This means that in order to be able to perform queries in a designated order or access the result, you'll have to use callbacks:

connection.query("SELECT * FROM TABLE").addCallback(function(result){
for (var i = 0, l = result.ROWS.length; i < l; i++){
var row = result.ROWS[i];
// do something with the data
}
});

connection.query("SELECT * FROM table");

To be truly non-blocking, you must use listeners. This means that in order to be able to perform queries in a designated order or access the result, you'll have to use callbacks:

connection.query("SELECT * FROM TABLE");
connection.on('result', function(result) {
for (var i = 0, l = result.ROWS.length; i < l; i++){
var row = result.ROWS[i];
// do something with the data
}

connection.removeListener('result', arguments.callee);
});

You **must** remember to remove your listener, otherwise it will be called along with any new listeners you create.

If you want to capture MySQL errors, subscribe to the 'error' event

connection.query("SELECT * FROM inexistent_table").addErrback(function(error, errno){
alert('mysql error! + ' error);
});

Aside from query, the commands `stat`, `client_info`, `host_info`, `server_version` and `client_version` are available, which provide the respective information about the server.
connection.query("SELECT * FROM inexistent_table")
connection.on('error', function(error, errno){
sys.puts('mysql error! + ' error);
});

Aside from query, the commands `stat`, `client_info`, `host_info`, `server_version` and `client_version` are available, which provide the respective information about the server. In order to preserve somewhat backwards compatibility, these have seperate events per function.

More Examples
-------------

mysql.on('result', function(result) {
this.fetch_object(result, function(obj) {
node.log(obj.Field);
});
}).query('DESCRIBE `stock`;');

You can use the fetch_object, fetch_array or fetch_args functions as shorthand to return either an object, an array or function callback arguments to retrieve your data.

mysql.on('result', function(result) {
this.fetch_array(result, function(arr) {
node.log(arr[0]);
});
}).query('DESCRIBE `stock`;');

Or

mysql.on('result', function(result) {
this.fetch_args(result, function(field, type) {
node.log(field);
});
}).query('DESCRIBE `stock`;');

Will produce the same output as the first example.

Installing DBSlayer
-------------------
Expand All @@ -54,23 +94,32 @@ Compile it according to the instructions [here](http://code.nytimes.com/projects

Then create a /etc/dbslayer.conf file defining a database. Here I'm defining the `cool` server which connects to my `mysql` database

[cool]
database=mysql
host=localhost
user=root
pass=1234
[cool]
database=mysql
host=localhost
user=root
pass=1234

Then run DBSlayer for that connection:

dbslayer -c /etc/dbslayer.conf -s cool
dbslayer -c /etc/dbslayer.conf -s cool

Test it by running test.js like this:

node test.js "SELECT * FROM help_category"
node test.js "SELECT * FROM help_category"

If you get a bunch of entries like in this [screenshot](http://cld.ly/9aosh) then dbslayer (and node.dbslayer.js) work!

Author
------
Authors
-------

Guillermo Rauch <[http://devthought.com](http://devthought.com)>

Robin Duckett <[http://www.twitter.com/robinduckett](http://www.twitter.com/robinduckett)>

Barry Ezell <[http://twitter.com/barryezl](http://twitter.com/barryezl)>

Contributors
------------

Guillermo Rauch <[http://devthought.com](http://devthought.com)>
Craig Condon <[http://spiceapps.com](http://spiceapps.com)>
111 changes: 80 additions & 31 deletions dbslayer.js
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,54 +1,62 @@
/*
---
name: dbslayer.js

description: Interface to DBSlayer for Node.JS

version: 0.2
author: [Guillermo Rauch](http://devthought.com)
updaters: [Robin Duckett](http://www.twitter.com/robinduckett),
[Barry Ezell](http://twitter.com/barryezl)
...
*/

var sys = require('sys'),
var util = require('util'),
http = require('http'),

booleanCommands = ['STAT', 'CLIENT_INFO', 'HOST_INFO', 'SERVER_VERSION', 'CLIENT_VERSION'],
events = require('events'),
booleanCommands = ['STAT', 'CLIENT_INFO', 'HOST_INFO', 'SERVER_VERSION', 'CLIENT_VERSION'];

Server = this.Server = function(host, port, timeout){
var Server = function(host, port, timeout) {
this.host = host || 'localhost';
this.port = port || 9090;
this.timeout = timeout;
};

Server.prototype.fetch = function(object, key){
var connection = http.createClient(this.port, this.host),
request = connection[connection.get ? 'get' : 'request']('/db?' + escape(JSON.stringify(object)), {'host': this.host}),
promise = new process.Promise();

promise.timeout(this.timeout);
util.inherits(Server, events.EventEmitter);
Server.prototype.fetch = function(object, key) {
var connection = http.createClient(this.port, this.host);
var request = connection.request('GET', '/db?' + escape(JSON.stringify(object)), {'host': this.host});
var server = this;

request.on('response', function(response) {
var allData = "";
response.setEncoding('utf8');
response.on('data', function(data) {
allData += data;
});

request.finish(function(response){
response.addListener('body', function(data){
response.on('end', function() {
try {
var object = JSON.parse(data);
} catch(e){
return promise.emitError(e);
}

if (object.MYSQL_ERROR !== undefined){
promise.emitError(object.MYSQL_ERROR, object.MYSQL_ERRNO);
} else if (object.ERROR !== undefined){
promise.emitError(object.ERROR);
} else {
promise.emitSuccess(key ? object[key] : object);
}
var object = JSON.parse(allData);
} catch(e) {
server.emit('error', e);
}

if (object !== undefined) {
if (object.MYSQL_ERROR !== undefined) {
server.emit('error', object.MYSQL_ERROR, object.MYSQL_ERRNO);
} else if (object.ERROR !== undefined) {
server.emit('error', object.ERROR);
} else {
server.emit(key.toLowerCase(), key ? object[key] : object);
}
}
});
});
return promise;

request.end();
};

Server.prototype.query = function(query){
return this.fetch({SQL: query}, 'RESULT');
this.fetch({SQL: query}, 'RESULT')
return this;
};

for (var i = 0, l = booleanCommands.length; i < l; i++){
Expand All @@ -59,4 +67,45 @@ for (var i = 0, l = booleanCommands.length; i < l; i++){
return this.fetch(obj, command);
};
})(booleanCommands[i]);
}
}

Server.prototype.fetch_object = function(res, callback) {
for (var row, i = 0; i < res.ROWS.length; row = res.ROWS[i], i++) {
var ret = {};
if (typeof row !== "undefined") {
for (var j = 0; j < res.HEADER.length; j ++) {
ret[res.HEADER[j]] = row[j];
}

callback.apply(this, [ret]);
}
}
};

Server.prototype.fetch_array = function(res, callback) {
for (var row, i = 0; i < res.ROWS.length; row = res.ROWS[i], i++) {
var ret = [];
if (typeof row !== "undefined") {
for (var j = 0; j < res.HEADER.length; j ++) {
ret[j] = row[j];
}

callback.apply(this, [ret]);
}
}
};

Server.prototype.fetch_args = function(res, callback) {
for (var row, i = 0; i < res.ROWS.length; row = res.ROWS[i], i++) {
var ret = [];
if (typeof row !== "undefined") {
for (var j = 0; j < res.HEADER.length; j ++) {
ret[j] = row[j];
}

callback.apply(this, ret);
}
}
};

exports.Server = Server;
8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "dbslayer",
"description": "mysql api for node.js",
"version": "0.2.0",
"main": "dbslayer.js",
"dependencies": {},
"devDependencies": {}
}
38 changes: 20 additions & 18 deletions test.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ description: <
It takes three parameters from the SQL query, a host

author: [Guillermo Rauch](http://devthought.com)
updaters: [Robin Duckett](http://www.twitter.com/robinduckett)
...
*/

Expand All @@ -20,24 +21,25 @@ if (!sql){
return;
}

db.query(sql)
// on success
.addCallback(function(result){
sys.puts('-------------------------');
for (var i = 0, l = result.ROWS.length; i < l; i++){
sys.puts('Row ' + i + ': ' + result.ROWS[i].join(' '));
}
})

// on error :(
.addErrback(function(error, errno){
sys.puts('-------------------------');
sys.puts('MySQL error (' + (errno || '') + '): ' + error);
});
db.addListener('result', function(result) {
sys.puts('-------------------------');
for (var i = 0, l = result.ROWS.length; i < l; i++){
sys.puts('Row ' + i + ': ' + result.ROWS[i].join(' '));
}
});

db.addListener('error', function(error, errno) {
sys.puts('-------------------------');
sys.puts('MySQL error (' + (errno || '') + '): ' + error);
});

['stat', 'client_info', 'host_info', 'server_version', 'client_version'].forEach(function(command){
db[command]().addCallback(function(result){
sys.puts('-------------------------');
db.query(sql);

['stat', 'client_info', 'host_info', 'server_version', 'client_version'].forEach(function(command) {
db.addListener(command, function(result) {
sys.puts('-------------------------');
sys.puts(command.toUpperCase() + ' ' + result);
});
});
db[command]();
});