自己实现PostgresQL的nodejs驱动,分享给大家

PostgresQL性能上不输Mysql,而且支持很多高级特性,于是我写了这个项目,根据libpg的c驱动,封装了这个nodejs驱动。

项目地址:

git clone https://code.csdn.net/limite_god/pgsql.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目录下执行

git clone https://code.csdn.net/limite_god/pgsql.git
cd pgsql
make

项目的makefile只支持linux,且及其简单,最有可能发生两类错误,一类是头文件找不到,一类是方法的实现着不到。

如果头文件未找到

1、检查nodejs及postgres是否安装

2、检查makefile中的头文件扫描目录是否和你系统的安装目录是否一致,如果不一致,请自己修改

如果提示方法实现未找到

这种情况一般是由于你的系统未把postgres的动态库加入系统扫描路径

尝试添加/etc/ld.so.conf.d/pgsql.conf,添加一行/usr/local/pgsql/lib(你的pg动态库的路径),然后执行ldconfig

DEMO

var async = require('async');
var pgsql = require('pgsql');
var DataBase = pgsql.DataBase;
var Table = pgsql.Table;
var Column = pgsql.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", 0, "primary key"),
        new Column("index", "SERIAL", 0, ""),
        new Column("name", "text", -1, ""),
        new Column("description", "text", -1, "")
    ]
);
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, data){
            console.log(data);
            cb(err);
        });
    },
    function(cb)
    {
        var t = db.get("test");
        var doc = {
            $set:{
                name:"just a test."
            }
        };
        t.update({id:3}, doc, function(err, data){
            console.log(data);
            cb(err);
        });
    },
    function(cb)
    {
        var t = db.get("test");
        var options = {
            limit:10,
            offset:0,
            sort:{
                id:-1
            }
        };
        t.find({id:3}, {}, options, function(err, data){
            console.log(data);
            cb(err);
        });
    },
    function(cb)    //save a set
    {
        var t = db.get("test");
        t.save({name:"liming", description:'a\'b'}, function(err, data){
            console.log(data);
            cb(err);
        });
    },
    function(cb)    //保存记录,并返回自增长的id
    {
        var t = db.get("test");
        var options = {
            ret:{
                id:1
            }
        };
        t.save({name:"liming", description:'a\'b'}, options, function(err, data){
            console.log(data);
            cb(err);
        });
    },
    function(cb)
    {
        var t = db.get("test");
        t.remove({name:"test222"}, function(err, data){
            console.log(data);
            cb(err);
        });
    },
    function(cb)    //跨表的语句,请使用db.execute直接执行
    {
        db.execute("select * from customer", function(err, data){
            console.log(data);
            cb(err);
        });
    },
    /* 执行事务 */
    function(cb){
        db.getConn(function(err, conn){
            cb(err, conn);
        });
    },
    function(conn, cb)
    {
        conn.execute("BEGIN", function(err, data){
            console.log(data);
            cb(err, conn);
        });
    },
    function(conn, cb)
    {
        conn.execute("DECLARE myportal CURSOR FOR select * from test", function(err, data){
            console.log(data);
            cb(err, conn);
        });
    },
    function(conn, cb)
    {
        var hasNext = true;
        async.whilst(
            //条件
            function() {
                return hasNext;   //true,则第二个函数会继续执行,否则,调出循环
            },
            function(whileCb) { //循环的主体
                conn.execute("FETCH NEXT in myportal", function(err, data){
                    if(data && data.affected > 0)
                    {
                        console.log(data);
                    }
                    else
                    {
                        hasNext = false;
                    }
                    whileCb(err);
                });
            },
            function(err) {         //here 如果条件不满足,或者发生异常
                cb(err, conn);
            }
        );
    },
    function(conn, cb)
    {
        conn.execute("CLOSE myportal", function(err, data){
            console.log(data);
            cb(err, conn);
        });
    },
    function(conn, cb)
    {
        conn.execute("END", function(err, data){
            console.log(data);
            cb(err, conn);
        });
    }
], function (err, conn) {
    if(conn)
    {
        //使用完连接,记得归还给连接池
        db.unLock(conn);
    }
    if(err)
    {
        console.log("the error is:");
        console.error(err);
    }
});

输出如下:

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, rst: [] }
insert into test(name,description) values('liming','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: [] }
{ affected: 1,
  rst: [ { id: 18, index: 18, name: 'liming', description: 'a\'b' } ] }
{ affected: 1,
  rst: [ { id: 19, index: 19, name: 'liming', description: 'a\'b' } ] }
{ affected: 1,
  rst: [ { id: 20, index: 20, name: 'liming', description: 'a\'b' } ] }
{ affected: 1,
  rst: [ { id: 21, index: 21, name: 'liming', description: 'a\'b' } ] }
{ affected: 1,
  rst: [ { id: 22, index: 22, name: 'liming', description: 'a\'b' } ] }
{ affected: 1,
  rst: [ { id: 23, index: 23, name: 'liming', description: 'a\'b' } ] }
{ affected: 0, rst: [] }
{ affected: 0, rst: [] }

时间: 2024-10-31 22:31:17

自己实现PostgresQL的nodejs驱动,分享给大家的相关文章

MongoDB 的 Nodejs 驱动基础

在学着写mongodb,用的nodejs.这里我把坑先记录好,以后可以慢慢找.这篇文章也慢慢更,为了篇幅简洁,全部略去对错误的处理. 基础操作: 1.增 1 var mongo = require('mongodb').MongoClient 2 var name = { 3 city: 'Wuhan', 4 country: 'China' 5 } 6 mongo.connect('mongodb://localhost:27017/test', function(err, db) { 7 v

nodejs应用mysql(纯属翻译)

原文点击这里 目录 Install Introduction Contributors Sponsors Community Establishing connections Connection options SSL options Terminating connections Pooling connections Pool options Pool events Closing all the connections in a pool PoolCluster PoolCluster

Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门

目录 简介 MongoDB安装(windows) MongoDB基本语法和操作入门(mongo.exe客户端操作) 库操作 插入 查询 修改 删除 存储过程 nodejs操作MongoDB 插入 查询 修改 删除 调用存储过程 写在之后... 简介 MongoDB 开源,高性能的NoSQL数据库:支持索引.集群.复制和故障转移.各种语言的驱动程序:高伸缩性: NoSQL毕竟还处于发展阶段,也有说它的各种问题的:http://coolshell.cn/articles/5826.html  官网地

分享的好处

分享的好处 分享对于技术人员的成长是非常有必要的,而且好处非常多,但是在部门内部的分享,不应该好高骛远,在不同的阶段应该侧重不同的内容和层次,这样才能收到效果,毕竟分享的人和听分享的人都投入了时间成本,如果没有收益,这件事情肯定无法长久的执行下去,而不持之以恒,那就真是纯形式主义了. 个人理解的阶段应该如下: 磨合期 磨合期可能是一个部门刚组建,也可能是有非常多新人刚刚加入部门,在这个阶段分享应该侧重实际操作和已经成型的规范及技术,将部门已经积累下来的一些传统传递下去,目标在于延续性,而不应该好

开源中国活动分享

周末无事约了以前同事去听了开源中国源创会的活动,感觉不错.简单说一下. docker最近真是很火,昨天才刚听完一个同事的分享,使用linux containers和aufs减少虚拟化的overhead,build ship and run,有好感.今天是七牛一哥们做的分享,docker适合做paas,vm适合做iaas,使用范围仍然不同,他们内部使用docker做云处理api调用.后面thought works的新开源ci框架go就使用docker做沙盒.go与jenkins相比,就是pipel

Nodejs和Mongodb的连接器Mongoose

简介 今天我们将学习Mongoose,什么是Mongoose呢,它于MongoDB又是什么关系呢,它可以用来做什么呢,介绍Mongoose之前,我们先简单了解一下MongoDB. MongoDB是一个开源的NoSQL数据库,相比MySQL那样的关系型数据库,它更显得轻巧.灵活,非常适合在数据规模很大.事务性不强的场合下使用.同时它也是一个对象数据库,没有表.行等概念,也没有固定的模式和结构,所有的数据以文档的形式存储(文档,就是一个关联数组式的对象,它的内部由属性组成,一个属性对应的值可能是一个

nodejs笔记--与MongoDB的交互篇(七)

原文地址:http://www.cnblogs.com/zhongweiv/p/node_mongodb.html 目录 简介 MongoDB安装(windows) MongoDB基本语法和操作入门(mongo.exe客户端操作) 库操作 插入 查询 修改 删除 存储过程 nodejs操作MongoDB 插入 查询 修改 删除 调用存储过程 写在之后... 简介 MongoDB 开源,高性能的NoSQL数据库:支持索引.集群.复制和故障转移.各种语言的驱动程序:高伸缩性: NoSQL毕竟还处于发

linux 搭建unixODBC ,并对接 PostgreSQL 9.3.4

环境:suse 11 ,64位的操作系统 unixODBC 版本:2.3.2 PostgreSQL 9.3.4 1 编译安装 unixODBC 下载 unixODBC :http://www.unixodbc.org/download.html 解压编译 tar -zxvf unixODBC-2.3.2.tar.gz cd unixODBC-2.3.2 ./configure --prefix=/opt/unixODBC make && make install 安装路径设置在 /opt/

将GitLab的数据库导入阿里云PostgreSQL RDS

GitLab的数据库用的是PostgreSQL,之前由于阿里云RDS不支持PostgreSQL,只能将GitLab的数据库部署在云服务器上. 6月1日得知阿里云推出了PostgreSQL RDS,于是立马将GitLab的数据库迁移至PostgreSQL RDS. 下面分享一下迁移的主要操作步骤: 1)在GitLab服务器上备份GitLab数据库 操作命令: sudo gitlab-rake gitlab:backup:create SKIP=db 注:这个命令原本是只备份数据库,但实际运行时也会