对libpq进行简单的c++封装

 

       最近项目需要用c++操作PostgreSQL,编译c++的libpqxx遇到太多问题,虽然搞定,但不适合项目开发和维护。且官网似乎对此第三方库并不推荐,所以就查阅了相关资料,封装了一个c++的hpp,用来操作数据库。代码如下:

 DBConn.h

#ifndef _DBCONN_HPP_
#define _DBCONN_HPP_

#include <iostream>
#include <string>
#include <libpq-fe.h>
#include <map>
using namespace std;

typedef map<int,map<string,string> > map_result;

class Conn
{
public:
    Conn(char *connstring);
    ~Conn();
    map_result Fetch(char *SQL);
    int Exec(char *SQL);
private:
 void FinishConnection(PGconn *conn);
 void Reset();
private:
    PGconn *_conn;
    const char *_conninfo;
    PGresult *_res;
};

#endif // _DBCONN_HPP_

 

DBConn.cpp

#include "DBConn.h"

Conn::Conn(char *connstring)
{
 _conninfo = connstring;
    _conn = PQconnectdb(_conninfo);
    if (PQstatus(_conn) != CONNECTION_OK)
    {
        fprintf(stderr, "Could not connect to db/n%s", PQerrorMessage(_conn));
        FinishConnection(_conn);
    }
}
Conn::~Conn()
{
 _conninfo = NULL;
    FinishConnection(_conn);
}
void Conn::Reset()

    PQfinish(_conn);
    _conn = PQconnectdb(_conninfo);
}

void Conn::FinishConnection(PGconn *conn)

    PQfinish(_conn);
}
 
map_result Conn::Fetch(char *SQL)

    int row, col;
    map_result results;
    map<string,string> pairs;
    // 检查连接
    if (PQstatus(_conn) != CONNECTION_OK)
    {
        this->Reset();
    }
    // 开始一个事物
    _res = PQexec(_conn, "BEGIN");
    if (PQresultStatus(_res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "Failed to BEGIN transaction /n%s", PQerrorMessage(_conn));
        PQclear(_res);
        FinishConnection(_conn);
    }
    // 建立游标
    string FinalSQL = string("DECLARE myportal CURSOR FOR ") + 
                      string(SQL);
    _res = PQexec(_conn,FinalSQL.c_str());
    if (PQresultStatus(_res) != PGRES_COMMAND_OK)
    { 
        fprintf(stderr, "QUERY FAILED/n%s/n", PQerrorMessage(_conn));
        PQclear(_res);
        FinishConnection(_conn);
    }
    PQclear(_res);
 
    _res = PQexec(_conn, "FETCH ALL in myportal");
    if (PQresultStatus(_res) != PGRES_TUPLES_OK)
    {
        fprintf(stderr, "FETCH ALL failed/n%s/n", PQerrorMessage(_conn));
        PQclear(_res);
        FinishConnection(_conn);
    }
    else 
    {
        for (row=0;row<PQntuples(_res);row++)
        {
            for(col=0;col<PQnfields(_res);col++)
            {
                pairs[PQfname(_res,col)] = PQgetvalue(_res, row, col);
            }
            results[row] = pairs;
        }
    }
    // 结束一个事物
    _res = PQexec(_conn, "END");
    if (PQresultStatus(_res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "Failed to END transaction /n%s", PQerrorMessage(_conn));
        PQclear(_res);
        FinishConnection(_conn);
    }
    return results;
}
int Conn::Exec(char *sql)
{
    // 检查连接
    if (PQstatus(_conn) != CONNECTION_OK)
    {
        this->Reset();
    }
    // 开始一个事物
    _res = PQexec(_conn, "BEGIN");
    if (PQresultStatus(_res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "Failed to BEGIN transaction /n%s/n", PQerrorMessage(_conn));
        PQclear(_res);
        FinishConnection(_conn);
    }
    // 执行插入
    _res = PQexec(_conn, sql);
    if (PQresultStatus(_res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "Failed to execute INSERT /n%s/n", PQerrorMessage(_conn));
        PQclear(_res);
        FinishConnection(_conn);
    }
    // 提交事物
    _res = PQexec(_conn, "COMMIT");
    if (PQresultStatus(_res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "Failed to COMMIT transaction/n%s/n", PQerrorMessage(_conn));
        PQclear(_res);
        FinishConnection(_conn);
    }
    // 结束一个事物
    _res = PQexec(_conn, "END");
    if (PQresultStatus(_res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "Failed to END transaction /n%s", PQerrorMessage(_conn));
        PQclear(_res);
        FinishConnection(_conn);
    }
    return 0;
}

 

main.cpp

#include <iostream>   
#include "DBConn.h" 
using namespace std; 
 
int main()

    map_result res; 
    Conn *postgres = new Conn("host=192.168.150.131 dbname=postgres user=enterprisedb password=mayong port=5432 connect_timeout=5"); 
    for( int i=0; i<4; ++i ) 
    {  
        postgres->Exec("insert into test (select nextval('s_id'), 'dog', 3)"); 
    }
    res = postgres->Fetch("SELECT * FROM test where name = 'dog'"); 
    map_result::iterator it = res.begin(); 
    for( ; it!=res.end(); ++it ) 
    { 
        cout << "ROW:" << it->first << endl; 
        map<string,string>::iterator itField = it->second.begin(); 
        for( ; itField!=it->second.end(); ++itField ) 
        { 
            cout << "Field:" << itField->first << "  Value:" << itField->second << endl; 
        } 
    }
   
    postgres->Exec("update test set name = 'cat' where name = 'dog'");
    cout << "--------------------------------" << endl;
    res = postgres->Fetch("SELECT * FROM test where name = 'cat'"); 
    it = res.begin(); 
    for( ; it!=res.end(); ++it ) 
    { 
        cout << "ROW:" << it->first << endl; 
        map<string,string>::iterator itField = it->second.begin(); 
        for( ; itField!=it->second.end(); ++itField ) 
        { 
            cout << "Field:" << itField->first << "  Value:" << itField->second << endl; 
        } 
    } 
   
    postgres->Exec("delete from test where name = 'cat'"); 
   
    delete postgres;
    return 0; 
}

 

 

运行结果如下:

ROW:0

Field:age  Value:3

Field:id  Value:243

Field:name  Value:dog

ROW:1

Field:age  Value:3

Field:id  Value:244

Field:name  Value:dog

ROW:2

Field:age  Value:3

Field:id  Value:245

Field:name  Value:dog

ROW:3

Field:age  Value:3

Field:id  Value:246

Field:name  Value:dog

--------------------------------

ROW:0

Field:age  Value:3

Field:id  Value:243

Field:name  Value:cat

ROW:1

Field:age  Value:3

Field:id  Value:244

Field:name  Value:cat

ROW:2

Field:age  Value:3

Field:id  Value:245

Field:name  Value:cat

ROW:3

Field:age  Value:3

Field:id  Value:246

Field:name  Value:cat

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值