访问:使用 libpq - C 库的 PostgreSql 数据库。






4.65/5 (11投票s)
一组使用 libpq - C 库来访问和操作 PostgreSql 数据库的类。
目标读者
本文是为初学者和不知道如何使用 C++ 类封装的 libpq - C API 访问 PostgreSql 数据库的开发人员编写的。
1. 引言
本文是我第一篇文章的延续,请访问: sdba.aspx
但在本文中,我将提供 PostgreSql 类。
PostgreSQL 是一个强大的关系数据库,它已经有超过 15 年的积极开发,因此它是一个非常成熟的数据库系统。
我们将把提供的 libpq - C API 封装在一组 C++ 类中。
Libpq 是 C 应用程序程序员与 PostgreSQL 交互的接口。 libpq 是一组库函数,允许客户端程序将查询传递给 PostgreSQL 后端服务器并接收这些查询的结果。
2. 获取 PostgreSQL
您可以使用此 URL 获取最新的 PostgreSQL 二进制文件/源代码
https://postgresql.ac.cn/download/
PostgreSQL 适用于许多平台,当我撰写本文时,版本 8 提供预构建的二进制文件用于
- 和其他…
要获取更新的列表和直接下载,请访问:https://postgresql.ac.cn/download/
5. C++ 接口。
该接口集由以下 5 个类组成
物理文件 |
类 |
|
1 |
Exception.h |
DataBaseError |
2 |
DataBase.h |
DataBase |
3 |
ResultSet.h |
ResultSet |
4 |
PostgreSql.h |
PostgreSql |
注意:前 3 个类与我的第一篇文章相同,因此要查看实现细节,请参阅:sdba.aspx
5.1 PostgreSql
class PostgreSql /// PostgreSql data base class /// https://postgresql.ac.cn/docs/8.3/interactive/libpq.html { friend class DataBase<PostgreSql>; public: PostgreSql() : _hasResult(false) { } virtual ~PostgreSql() { } void connect(const std::string& server, const std::string& user, const std::string& password, const std::string& database) { _connectionHandlerPtr = PQsetdbLogin( server.c_str(), NULL, NULL, NULL, database.c_str(), user.c_str(), password.c_str() ); // Check to see that the backend connection was successfully made if (PQstatus(_connectionHandlerPtr) != CONNECTION_OK) { std::string msg("Failed to connect to database: Error: " + std::string(PQerrorMessage(_connectionHandlerPtr))); PQfinish(_connectionHandlerPtr); throw DataBaseError(msg); } } void execute(const std::string& sql) { std::cout << sql << std::endl; if(_hasResult) PQclear(_resultPtr); _resultPtr = PQexec(_connectionHandlerPtr, sql.c_str()); if(_resultPtr == NULL) { throw DataBaseError("Failed to execute sql: Error: " + std::string(PQerrorMessage(_connectionHandlerPtr))); } _status = PQresultStatus(_resultPtr); if ((_status == PGRES_EMPTY_QUERY) || (_status == PGRES_BAD_RESPONSE) || (_status == PGRES_FATAL_ERROR)) { PQclear(_resultPtr); _hasResult = false; throw DataBaseError("Failed to execute sql: Error: " + std::string(PQresStatus(_status)) + " : " + std::string(PQerrorMessage(_connectionHandlerPtr))); } (_status != PGRES_TUPLES_OK) ? PQclear(_resultPtr) : _hasResult = true; } void populate(ResultSet& rs) { if(_status != PGRES_TUPLES_OK) throw DataBaseError("This command don't support results"); if(_hasResult == false) throw DataBaseError("Any results available"); unsigned int num_tuples = PQntuples(_resultPtr); unsigned int num_fields = PQnfields(_resultPtr); for(int i = 0; i < num_tuples; ++i) { std::vector<std::string> myRow; for(int j = 0; j < num_fields; ++j) { myRow.push_back(PQgetvalue(_resultPtr, i, j)); } rs.addRow(myRow); } PQclear(_resultPtr); _hasResult = false ; } protected: void close(void) /// close the connection to the database and cleanup { PQfinish(_connectionHandlerPtr); } private: ExecStatusType _status; bool _hasResult; PGresult* _resultPtr; PGconn* _connectionHandlerPtr; }; // PostgreSql
此类是 PostgreSql 的实现,在其中我们使用 C API 来操作/访问数据。
我将从以下内容开始:PGconn* _connectionHandlerPtr; 这是数据库连接的句柄,几乎所有 PostgreSQL 函数都使用它。
在 void connect(...) 中,我们使用以下 API 函数
PQsetdbLogin(...)
PQstatus(...)
PQfinish(...)
https://postgresql.ac.cn/docs/8.3/interactive/libpq-connect.html
请注意,所有这些函数都使用:_connectionHandlerPtr;
在 execute(..) 中,我们使用以下 API 函数
PQclear(...)
Pqexec(...)
PqresultStatus(...)
https://postgresql.ac.cn/docs/8.3/interactive/libpq-exec.html
在 populate(...) 中,我们使用以下 API 函数
PQntuples(...)
PQnfields(...)
PQgetvalue(...)
https://postgresql.ac.cn/docs/8.3/interactive/libpq-exec.html
最后,我们有 close(),它使用:
PQfinish(...)
https://postgresql.ac.cn/docs/8.3/interactive/libpq-connect.html
关闭与服务器的连接。 还会释放 PGconn 对象使用的内存。
好的,就是这些,我们使用 PostgreSQL C API 的 10 个函数来构建这组类,这些类提供对 PostgreSQL 数据库的简单访问/操作。
6. 使用接口。
在这里,我将展示如何使用我们的类集,请参见
int main(int argc, char** argv) { try { ResultSet rs1, rs2; std::vector<std::string> row; DataBase<PostgreSql /* or MySql */> dataBase("205.178.146.71", "dot", "Dot.Fidelity1", "dot"); // table one // dataBase << "DROP TABLE if exists tblTest1"; dataBase << "CREATE TABLE if not exists tblTest1(test char(15) NOT NULL, testInt INT NULL, Constraint PK Primary Key(test))"; dataBase << "DELETE FROM tblTest1"; dataBase << "INSERT INTO tblTest1(test, testInt) VALUES('00', 1)" ; dataBase << "INSERT INTO tblTest1(test) VALUES('01')" ; dataBase << "INSERT INTO tblTest1(test) VALUES('02')" ; dataBase << "INSERT INTO tblTest1(test) VALUES('03')" ; // table two // dataBase << "DROP TABLE tblTest2"; dataBase << "CREATE TABLE if not exists tblTest2(test char(15) NOT NULL, dt DATE NULL, Constraint PK Primary Key(test))"; dataBase << "DELETE FROM tblTest2"; dataBase << "INSERT INTO tblTest2(test, dt) VALUES('01', '1979/11/14')" ; dataBase << "INSERT INTO tblTest2(test) VALUES('02')" ; dataBase << "INSERT INTO tblTest2(test) VALUES('03')" ; dataBase << "INSERT INTO tblTest2(test) VALUES('04')" ; dataBase << "SELECT * FROM tblTest1, tblTest2 WHERE tblTest1.test = tblTest2.test", rs1; dataBase << "SELECT * FROM tblTest2 WHERE test = '01'", rs2; std::string value; while(rs1.fetch(0, value)) { std::cout << value << std::endl; } while(rs2.fetch(1, value)) { std::cout << value << std::endl; } while(rs1.fetch(row)) { for (size_t i = 0; i < row.size(); i++) { std::cout << row[i] << " | "; } } while(rs2.fetch(row)) { for (size_t i = 0; i < row.size(); i++) { std::cout << row[i] << " | "; } } std::cout << rs1.get(0)[0] << " | " << rs1.get(0)[1] << std::endl; std::cout << rs2.get(0, 1) << std::endl; } catch (const DataBaseError& e) { std::cout << e.what() << std::endl; } return 0; }
7. 结论。
今天,PostgreSQL 是一个功能强大的开源关系数据库的选择之一,它提供快速的性能、高可靠性、易用性、成本节省,以及许多语言的访问 API,这些 API 广泛可用且易于使用。
致谢
参考文献
PostgreSQL
网站
https://postgresql.ac.cn/docs/
C++ 书籍(列表)
此处列出的 Web 链接将来可能无效。