Postgresql性能上不输MysqL,而且支持很多高级特性,于是我写了这个项目,根据libpg的c驱动,封装了这个nodejs驱动。
项目地址:
@H_
502_6@git clone https://code.csdn.net/limite_god/pg
sql.git
开发难点、待实现功能、特性
1、nodejs的v0.12.0开始,api有了不少变化,熟悉这些变化用来不少时间;
2、libpg-c的api的熟悉,全英文的,得一行行认真看;
3、makefile,这里面的知识杂而细,只写了个linux下编译的;
4、libpg的executeParam方法暂未实现,所以添加了escape的连接池,专门用来处理escape;
5、数据类型支持,现在只对libpg的int4及int8做了转换,其它格式会返回字符串(比如日期);
6、连接池使用了nodejs的EventEmitter实现,sql命令会在压力较大的时候进行排队,这一块策略非常重要,涉及了nodejs的核心思想,尽量发挥慢速资源的最大性能,Pool.js,大家可以细看;
7、Database对象cmPool和trPool、esPool,cm处理无需声明事务的sql,tr用来专门执行事务连接,es专门用来escape字符串;
8、api尽量做到给调用者最大的自由,协调资源交给驱动。
9、很多地方注释缺少,等待以后添加;
10、table实现了类mongodb的find,update,remove,save,都可以传递options参数,options参数暂时只支持4个key,ret,sort,limit,offset;
11、我会持续对项目进行维护,添加更多功能,有建议请留言。
环境准备
操作系统centos6+,安装nodejs版本v0.12.0+,postgresql版本9.4.1
需要说明的是,nodejs和postgresql都需要从源码安装,postgress的安装目录采用默认目录,/usr/local/pgsql/,如果你的目录不同,请修改项目跟目录下的makefile
下载代码并编译
模块并没有在官方模块中
注册,所以最好在你的nodejs程序的node_modules目录下执行
@H_
502_6@git clone https://code.csdn.net/limite_god/pg
sql.git
@H_
502_6@cd pg
sql
make
项目的makefile只
支持linux,且及其简单,最有可能发生两类
错误,一类是头
文件找不到,一类是
方法的实现着不到。
@H_
301_66@如果头
文件未找到
1、检查nodejs及postgres是否安装
2、检查makefile中的头
文件扫描目录是否和你系统的安装目录是否一致,如果不一致,请自己
修改
@H_
301_66@如果
提示方法实现未找到
这种情况一般是由于你的系统未把postgres的动态库加入系统扫描路径
尝试
添加/etc/ld.so.conf.d/pg
sql.conf,
添加一行/usr/local/pg
sql/lib(你的pg动态库的路径),然
后执行ldconfig
DEMO
@H_
502_6@var async = require('async');
@H_
502_6@var pg
sql = require('pg
sql');
var DataBase = pg
sql.DataBase;
var Table = pg
sql.Table;
var Column = pg
sql.Column;
var db = new DataBase({
url:"host=127.0.0.1 dbname=test user=postgres",cmPoolSize:20,//通过table.find,update,remove,save都使用这个连接池的连接
trPoolSize:5,//db.getConn获得连接都是这个连接池的连接
esPoolSize:1 //这个一个连接的连接池专门用来执行escape
});
var testTable = new Table("test",[
new Column("id","SERIAL","primary key"),new Column("index",""),new Column("name","text",-1,new Column("description","")
]
);
testTable.colList['description'].escape = true; //需要对文本进行转义
db.put(testTable);
async.waterfall([
function(cb){ //连接
数据库
db.init(function(err,data){
console.log(data);
cb(err);
});
},function(cb)
{
var t = db.get("test");
console.log(t.getDdl());
t.find({id:3},{},function(err,function(cb)
{
var t = db.get("test");
var doc = {
$set:{
name:"just a test."
}
};
t.update({id:3},doc,function(cb)
{
var t = db.get("test");
var options = {
limit:10,offset:0,sort:{
id:-1
}
};
t.find({id:3},options,function(cb) //save a set
{
var t = db.get("test");
t.save({name:"liming",description:'a\'b'},function(cb) //保存记录,并返回自增长的id
{
var t = db.get("test");
var options = {
ret:{
id:1
}
};
t.save({name:"liming",function(cb)
{
var t = db.get("test");
t.remove({name:"test222"},function(cb) //跨表的语句,请使用db.execute直接执行
{
db.execute("select * from customer",/* 执行事务 */
function(cb){
db.getConn(function(err,conn){
cb(err,conn);
});
},function(conn,cb)
{
conn.execute("BEGIN",data){
console.log(data);
cb(err,cb)
{
conn.execute("DECLARE myportal CURSOR FOR select * from test",cb)
{
var hasNext = true;
async.whilst(
//条件
function() {
return hasNext; //true,则第二个
函数会继续执行,否则,调出循环
},function(whileCb) { //循环的主体
conn.execute("FETCH NEXT in myportal",data){
if(data && data.affected > 0)
{
console.log(data);
}
else
{
hasNext = false;
}
whileCb(err);
});
},function(err) { //here 如果条件不满足,或者发生异常
cb(err,conn);
}
);
},cb)
{
conn.execute("CLOSE myportal",cb)
{
conn.execute("END",conn);
});
}
],function (err,conn) {
if(conn)
{
//使用完连接,记得归还给连接池
db.unLock(conn);
}
if(err)
{
console.log("the error is:");
console.error(err);
}
});
输出如下:
@H_
502_6@init success!
create table test(id SERIAL primary key,index SERIAL,name text,description text );
select * from test where (id = '3')
{ affected: 0,rst: [] }
update test set name = 'just a test.' where (id = '3')
{ affected: 0,rst: [] }
select * from test where (id = '3') order by id desc limit 10
{ affected: 0,rst: [] }
insert into test(name,description) values('liming','a''b')
{ affected: 1,'a''b') returning id
{ affected: 1,rst: [ { id: 23 } ] }
delete from test where (name = 'test222')
{ affected: 0,rst: [] }
{ affected: 1,rst:
[ { id: 1,username: 'liming',password: '123456',reg_time: '2015-03-25 22:26:30',type: 1,status: 1 } ] }
{ affected: 0,rst: [] }
{ affected: 0,rst: [ { id: 18,index: 18,name: 'liming',description: 'a\'b' } ] }
{ affected: 1,rst: [ { id: 19,index: 19,rst: [ { id: 20,index: 20,rst: [ { id: 21,index: 21,rst: [ { id: 22,index: 22,rst: [ { id: 23,index: 23,description: 'a\'b' } ] }
{ affected: 0,rst: [] }