Работа с PostgreSQL из C/C++

Работа с PostgreSQL из C/C++

Разработаем приложение которое в последствии должно взаимодействовать с базой данных PostgreSQL.
Есть две официальных клиентских C++ API для работы с PostgreSQL:
libpq++, libpqxx и SOCI PostgreSQL backend, с поддержкой PostgreSQL >= 7.3, версии старше 8.0. Они распространяются свободно, с открытым исходным кодом и «хорошо документированы» на английском языке.

Работа с библиотекой libpq++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATE TABLE people (
        id              INTEGER,
        firstname       VARCHAR(20),
        lastname        VARCHAR(20),
        phonenumber     CHAR(10)
);
 
INSERT INTO people (id, firstname, lastname, phonenumber) VALUES
        (1, 'Вася', 'Пупкин', '5055551234');
 
INSERT INTO people (id, firstname, lastname, phonenumber) VALUES
        (2, 'Лена', 'Похер', '5055551234');
 
INSERT INTO people (id, firstname, lastname, phonenumber) VALUES
        (3, 'Серёжа', 'молодец', '5055554321');

Для этой программы для C++ использую библиотеку libpq что бы получить доступ в базу. Для C программиста лучше использовать родные С библиотеки через C++ libpq и эта библиотека очень доступна для на-С++ программита.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  #include <stdio.h>
  #include <postgresql/libpq-fe.h>
  #include <string>
 
int     main() {
 PGconn          *conn;
 PGresult        *res;
 int             rec_count;
 int             row;
 int             col;
 
 conn = PQconnectdb("dbname=ljdata host=localhost user=dataman password=supersecret");
 if (PQstatus(conn) == CONNECTION_BAD) {
          puts("Не удается подключиться к базе данных");
          exit(0);
 }
 res = PQexec(conn, "update people set phonenumber=\'5055559999\' where id=3");
 res = PQexec(conn, "select lastname,firstname,phonenumber from people order by id");
 
 if (PQresultStatus(res) != PGRES_TUPLES_OK) {
            puts("Мы не получили данные");
            exit(0);
 }
 
 rec_count = PQntuples(res);
 
printf("Мы получили %d записей.\n", rec_count);
puts("==========================");
 
for (row=0; row<rec_count; row++) {
     for (col=0; col<3; col++) {
           printf("%s\t", PQgetvalue(res, row, col));
      }
                 puts("");
}
 
puts("==========================");
PQclear(res);
PQfinish(conn);
return 0;
}

Компиляция:

g++ -lpq db.cpp -o db

Использование libpqxx

Вот несколько причин для выбора libpqxx:

  1. Согласованность с языком. Используются преимущества C++: шаблоны (templates), исключения (exceptions), различные итераторов.
    По возможности внутри юзается стандартные вещи из STL.
  2. Структура, позволяющая писать «хороший» код. В основном проблемы обнаруживаются
    на этапе компиляции или тестирования.
  3. Мощность. Встроенные фичи: автоматическое восстановление соединения и
    управление транзакциями освобождают разработчика.
  4. Гибкость. Код библиотеки живет в своем пространстве имен (pqxx)
    и полностью прячет нативный C API.

    Что нужно для libpqxx?

    Во-первых, необходима нативная libpq.so/libpq.dll.
    Во-вторых, сама libpqxx.so/libpqxx.dll.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    
    #include <pqxx/connection>
    #include <pqxx/transaction>
    #include <iostream>
    #include <string>
    #include <sstream>
     
    void help()
    {
       std::cout << "Использовать: <host> <user> <password> <database>" << std::endl;
    }
     
    int main(int argc, char **argv)
    {
       if (argc < 5) {
           help();
           return 1;
       }
     
       // Prepare connection string
       std::ostringstream conn_string("");
       conn_string << "host=" << argv[1]
           << " user=" << argv[2]
           << " password=" << argv[3]
           << " dbname=" << argv[4];
     
       do {
           // Create connection
           try {
               pqxx::connection conn(conn_string.str());
               pqxx::work       xact(conn, "SampleSelect");
     
               std::string      query("SELECT * from people limit 3");
               // Execute query
               try {
                   pqxx::result res = xact.exec(query);
                   if (!res.size()) {
                       std::cout << "Пустой вывод." << std::endl;
                       break;
                   }
                   // Show results
                   for (pqxx::result::const_iterator i = res.begin(), r_end = res.end(); i != r_end; ++i) {
                       // Iterate fields
                       for (pqxx::result::const_fielditerator f = i->begin(), f_end = i->end(); f != f_end; ++f) {
                           std::cout << f->name() << " = '" << f->c_str() << "'" << std::endl;
                       }
                       std::cout << std::endl;
                   }
               } catch (...) {
                   std::cout << "Запрос не был выполнен: " << query << std::endl;
                   break;
               }
           } catch (pqxx::broken_connection) {
               std::cout << "Ошибка: establish connection." << std::endl;
               break;
           }
           std::cout << "Запрос успешно выполнен." << std::endl;
     
           return 0;
       } while (false);
     
       return 1;
    }

    Makefile:

    1
    2
    3
    4
    5
    6
    7
    
    SRC=pqxx_sample.cpp
    PROG=pqxx_sample
     
    all:
     c++ ${SRC} -o ${PROG} `pkg-config --libs --cflags libpqxx`
    clean:
     rm -f *.o ${PROG}
    1. libpq++ – libpqplusplus.html
    2. libpqxx – libpqxx
    3. Справочная информация – Reference
    4. std::ostringstream – ostringstream

    Библиотека SOCI PostgreSQL backend поддерживает:

    1. Oracle
    2. PostgreSQL >= 7.3, версии старше 8.0
    3. MySQL
    4. (unsupported) backends exist in the CVS repository: ODBC, SQLite and Firebird.

    Тестированные платформы

    PostgreSQL версии Операционная система Компилятор
    8.3 Mac OS X 10.5.3 g++ 4.0.1
    8.3 Mac OS X 10.5.3 g++ 4.4.0
    8.3 FreeBSD 7.0 g++ 4.2.1
    8.3 Linux i686 2.6.9 (RedHat family) g++ 3.4.6
    8.2.7 Linux i686 2.6.23 (Fedora release 7) g++ 4.1.2

    Поддерживаемые backend-ы и поддерживаемые платформы

    Oracle PostgreSQL MySQL SQLite3 Firebird ODBC
    Binding by Name YES YES (>=8.0) YES YES YES YES
    Dynamic Binding YES YES YES YES YES YES
    Bulk Operations YES YES YES YES YES YES
    Transactions YES YES YES
    (with servers that support them, usually >= 4.0)
    YES YES YES
    BLOB Data Type YES YES NO NO YES NO
    RowID Data Type YES YES NO NO NO NO
    Nested Statements YES NO NO NO NO NO
    Stored Procedures YES YES NO (but stored functions, YES) NO YES NO

    Какие требуются клиентские библиотеки

    SOCI PostgreSQL backend требует PostgreSQL’s libpq клиентскую библиотеку.

    Пример:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    
    #include "soci.h"
    #include "soci-oracle.h"
    #include <iostream>
    #include <istream>
    #include <ostream>
    #include <string>
    #include <exception>
     
    using namespace soci;
    using namespace std;
     
    bool getName(string &name)
    {
        cout << "Введите имя: ";
        return cin >> name;
    }
     
    int main()
    {
        try
        {
            session sql(postgresql, "service=mydb user=john password=secret");
     
            int count;
            sql << "select count(*) from phonebook", into(count);
     
            cout << "У нас " << count << " записей в phonebook.\n";
     
            string name;
            while (getName(name))
            {
                string phone;
                indicator ind;
                sql << "select phone from phonebook where name = :name",
                    into(phone, ind), use(name);
     
                if (ind == i_ok)
                {
                    cout << "Телефонный номер: " << phone << '\n';
                }
                else
                {
                    cout << "Нет телефонного номера: " << name << '\n';
                }
            }
        }
        catch (exception const &e)
        {
            cerr << "Ошибка: " << e.what() << '\n';
        }
    }

Comments to Работа с PostgreSQL из C/C++

  • Пожалуйста, можете детально описать, как компилировать библиотеку с libpqxx?

    Sergey 30.11.2011 17:13 Ответить
  • Судя по тексту — это низкокачественный перевод. «на-С++ программита» — хороший пример использования плохого переводчика. Полагаю автор не ответит.

    Dima 20.11.2012 17:04 Ответить

Leave a Comment

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Загрузка...
Menu Title