自己實現PostgresQL的nodejs驅動,分享給大家

來源:互聯網
上載者:User

標籤:nodejs   postgresql   驅動   

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 pgsqlmake

項目的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: [] }


自己實現PostgresQL的nodejs驅動,分享給大家

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.