65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.65/5 (11投票s)

2009年4月7日

CPOL

2分钟阅读

viewsIcon

79523

downloadIcon

2031

一组使用 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/

https://postgresql.ac.cn/docs/

C++ 书籍(列表)

http://www.amazon.com/C%2B%2B-Books/lm/R1FWITBSD4E82F/ref=cm_lm_byauthor_title_full/103-7510116-1265448

此处列出的 Web 链接将来可能无效。

© . All rights reserved.