对libpq进行简单的c++封装
2011-08-05 10:46
405 查看
最近项目需要用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
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
相关文章推荐
- 对libpq进行简单的c++封装
- 使用C++进行WMI查询的简单封装
- 对回调函数进行简单封装
- 一个简单封装用户命令的C++程序
- GreenDao数据库框架 最精简使用教程 并对其进行简单封装
- 在C/C++代码中使用SSE等指令集的指令(5)SSE进行加法运算简单的性能测试
- 一个使用超简单C++封装的网络库(包含服务器端和客户端,跨平台,比较适用于移动终端)
- 在C#中使用C++编写的类——用托管C++进行封装[转]
- js中用数组对一些验证进行简单的封装
- Safe C++ 读书笔记:对基本数据类型进行封装,以编写更安全的C++代码
- 对数据库DML操作进行封装成简单的工具
- C++使用sqlite3进行简单的课表管理
- Mybatis 进行简单通用的封装
- 对位操作的C++的简单封装
- [Qt] 运用QtConcurrent中的MapReduce模型进行简单的C++并行运算
- 在C/C++代码中使用SSE等指令集的指令(5)SSE进行加法运算简单的性能测试
- c++关于封装、接口的简单理解
- C++之对同步对象进行封装包装
- C++简单封装pthread
- 使用闭包对setTimeout进行简单封装