PostgreSQL - Интерфейс C/C++
В данном разделе мы будем использовать библиотеку libpqxx, являющуюся клиентским API для PostgreSQL, написанным на языке С++. Исходный код libpqxx доступен под лицензией BSD, поэтому Вы можете свободно загружать его, передавать другим, изменять, продавать, включать в свой собственный код и делиться изменениями с другими пользователями на Ваше усмотрение.
Установка
Последнюю версию библиотеки libpqxx можно скачать по ссылке Download Libpqxx. Скачайте ее и выполните следующие шаги:
wget http://pqxx.org/download/software/libpqxx/libpqxx-4.0.tar.gz tar xvfz libpqxx-4.0.tar.gz cd libpqxx-4.0 ./configure make make install
Перед началом использования интерфейса C/C++ для PostgreSQL найдите файл pg_hba.conf в каталоге установки PostgreSQL и добавьте следующую линию:
# IPv4 local connections: host all all 127.0.0.1/32 md5
Вы можете перезагрузить сервер postgres, если он еще не запущен, при помощи следующей команды:
[root@host]# service postgresql restart Stopping postgresql service: [ OK ] Starting postgresql service: [ OK ]
Для коммерческого использования:
-
Arenadata DB (ADB) – масштабируемое хранилище корпоративных данных, использующее массовую параллельную обработку и построенное на базе СУБД Greenplum с открытым исходным кодом Предназначен для хранения, обработки и анализа больших объемов структурированных и полуструктурированных данных – до десятков петабайт.

-
Postgres Pro – российская коммерческая СУБД, разработанная компанией Postgres Professional с использованием СУБД PostgreSQL с открытым исходным кодом, которая использует и расширяет язык SQL в сочетании со многими функциями, позволяющими безопасно хранить и масштабировать самые сложные рабочие нагрузки данных, но значительно переработанная для соответствия требованиям корпоративных заказчиков.

API C/C++
Ниже приведены важные подпрограммы интерфейса, необходимые для работы с базой данных PostgreSQL из Вашей программы C/C++. Если Вы ищете более сложное приложение, тогда рекомендуем Вам изучить официальную документацию libpqxx или использовать коммерчески доступные API.
|
S. No. |
API и Описание |
|
1 |
pqxx::connection C( const std::string & dbstring ) Это typedef, который будет использоваться для подключения к базе данных. Здесь dbstring предоставляет необходимые параметры для подключения к базе данных, например, dbname = testdb user = postgres password=pass123 hostaddr=127.0.0.1 port=5432.
Если подключение установлено успешно, он создает C с объектом подключения, который предоставляет различные полезные функции. |
|
2 |
C.is_open() Метод is_open() вернет 1, если файл найден и успешно открыт. Иначе вернет 0 и сработает код прописанный в блоке else. Если файл не открыт – желательно обработать ошибку. Как правило, если вся работа программы связана с файлом, пишут некое сообщение в консоль, и ставят выход из программы. |
|
3 |
C.disconnect() Данный метод используется для отключения от соединения с открытой базой данных. |
|
4 |
pqxx::work W( C ) Это typedef, который будет использоваться для создания транзакционного объекта с использованием соединения C, который в конечном итоге будет использоваться для выполнения операторов SQL в транзакционном режиме.
Если объект транзакции создан успешно, он присваивается переменной W, которая будет использоваться для доступа к общедоступным методам, связанным с транзакционным объектом. |
|
5 |
W.exec(const std::string & sql) Данный метод используется для выполнения команды SQL. |
|
6 |
W.commit() Данный метод используется для подтверждения транзакции. |
|
7 |
W.abort() Данный метод используется для того, чтобы откатить транзакцию назад. |
|
8 |
pqxx::nontransaction N( C ) Это typedef, который используется для создания нетранзакционного объекта с использованием соединения C, который в конечном итоге будет использоваться для выполнения операторов SQL в нетранзакционном режиме.
Если объект транзакции создан успешно, он присваивается переменной N, которая будет использоваться для доступа к общедоступным методам, связанным с нетранзакционным объектом. |
|
9 |
N.exec(const std::string & sql) Этот общедоступный метод используется для выполнения оператора SQL и возвращает объект результата, который на самом деле является интегратором, содержащим все возвращаемые записи. |
Подключение к базе данных
Следующие сегменты кода C показывают, как подключиться к существующей базе данных, открытой на компьютере через порт 5432. В данном случае используется обратный слеш \ для продолжения линии.
#include <iostream>
#include <pqxx/pqxx>
using namespace std;
using namespace pqxx;
int main(int argc, char* argv[]) {
try {
connection C("dbname = testdb user = postgres password = cohondob \
hostaddr = 127.0.0.1 port = 5432");
if (C.is_open()) {
cout << "Opened database successfully: " << C.dbname() << endl;
} else {
cout << "Can't open database" << endl;
return 1;
}
C.disconnect ();
} catch (const std::exception &e) {
cerr << e.what() << std::endl;
return 1;
}
}
Теперь давайте скомпилируем и запустим указанную выше программу для подключения к нашей базе данных testdb, к которой можно получить доступ с помощью имени пользователя postgres и пароля pass123.
Вы можете использовать логин и пароль в зависимости от настроек Вашей базы данных. Не забудьте сохранить -lpqxx и -lpq в указанном порядке! В противном случае компоновщик будет ругаться из-за отсутствия функций с именами, начинающимися с «PQ».
$g++ test.cpp -lpqxx -lpq $./a.out Opened database successfully: testdb
Создание таблицы
Следующий сегмент кода C используется для создания таблицы в предварительно созданной базе данных:
#include <iostream>
#include <pqxx/pqxx>
using namespace std;
using namespace pqxx;
int main(int argc, char* argv[]) {
char * sql;
try {
connection C("dbname = testdb user = postgres password = cohondob \
hostaddr = 127.0.0.1 port = 5432");
if (C.is_open()) {
cout << "Opened database successfully: " << C.dbname() << endl;
} else {
cout << "Can't open database" << endl;
return 1;
}
/* Create SQL statement */
sql = "CREATE TABLE COMPANY(" \
"ID INT PRIMARY KEY NOT NULL," \
"NAME TEXT NOT NULL," \
"AGE INT NOT NULL," \
"ADDRESS CHAR(50)," \
"SALARY REAL );";
/* Create a transactional object. */
work W(C);
/* Execute SQL query */
W.exec( sql );
W.commit();
cout << "Table created successfully" << endl;
C.disconnect ();
} catch (const std::exception &e) {
cerr << e.what() << std::endl;
return 1;
}
return 0;
Когда выше описанная программа скомпилирована и выполнена, появится таблица COMPANY в Вашей базе данных testdb, и Вы увидите следующие уведомления:
Opened database successfully: testdb Table created successfully
Операция INSERT
Следующий сегмент кода С показывает, как создать записи в таблице COMPANY:
#include <iostream>
#include <pqxx/pqxx>
using namespace std;
using namespace pqxx;
int main(int argc, char* argv[]) {
char * sql;
try {
connection C("dbname = testdb user = postgres password = cohondob \
hostaddr = 127.0.0.1 port = 5432");
if (C.is_open()) {
cout << "Opened database successfully: " << C.dbname() << endl;
} else {
cout << "Can't open database" << endl;
return 1;
}
/* Create SQL statement */
sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " \
"VALUES (1, 'Paul', 32, 'California', 20000.00 ); " \
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " \
"VALUES (2, 'Allen', 25, 'Texas', 15000.00 ); " \
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" \
"VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );" \
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" \
"VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );";
/* Create a transactional object. */
work W(C);
/* Execute SQL query */
W.exec( sql );
W.commit();
cout << "Records created successfully" << endl;
C.disconnect ();
} catch (const std::exception &e) {
cerr << e.what() << std::endl;
return 1;
}
return 0;
}
Когда описанная выше программа скомпилирована и выполнена, она создаст введенные записи в таблицу COMPANY, и Вы увидите следующие уведомления:
Opened database successfully: testdb Records created successfully
Операция SELECT
Следующий сегмент кода С показывает, как мы выбираем и отображаем записи из созданной таблицы COMPANY:
#include <iostream>
#include <pqxx/pqxx>
using namespace std;
using namespace pqxx;
int main(int argc, char* argv[]) {
char * sql;
try {
connection C("dbname = testdb user = postgres password = cohondob \
hostaddr = 127.0.0.1 port = 5432");
if (C.is_open()) {
cout << "Opened database successfully: " << C.dbname() << endl;
} else {
cout << "Can't open database" << endl;
return 1;
}
/* Create SQL statement */
sql = "SELECT * from COMPANY";
/* Create a non-transactional object. */
nontransaction N(C);
/* Execute SQL query */
result R( N.exec( sql ));
/* List down all the records */
for (result::const_iterator c = R.begin(); c != R.end(); ++c) {
cout << "ID = " << c[0].as<int>() << endl;
cout << "Name = " << c[1].as<string>() << endl;
cout << "Age = " << c[2].as<int>() << endl;
cout << "Address = " << c[3].as<string>() << endl;
cout << "Salary = " << c[4].as<float>() << endl;
}
cout << "Operation done successfully" << endl;
C.disconnect ();
} catch (const std::exception &e) {
cerr << e.what() << std::endl;
return 1;
}
return 0;
Как только вышеописанная программа скомпилирована и выполнена, она выдаст следующий результат:
Opened database successfully: testdb ID = 1 Name = Paul Age = 32 Address = California Salary = 20000 ID = 2 Name = Allen Age = 25 Address = Texas Salary = 15000 ID = 3 Name = Teddy Age = 23 Address = Norway Salary = 20000 ID = 4 Name = Mark Age = 25 Address = Rich-Mond Salary = 65000 Operation done successfully
Операция UPDATE
Следующий сегмент кода С показывает, как использовать UPDATE для обновления выделенных записей в таблице COMPANY и их отображения:
#include <iostream>
#include <pqxx/pqxx>
using namespace std;
using namespace pqxx;
int main(int argc, char* argv[]) {
char * sql;
try {
connection C("dbname = testdb user = postgres password = cohondob \
hostaddr = 127.0.0.1 port = 5432");
if (C.is_open()) {
cout << "Opened database successfully: " << C.dbname() << endl;
} else {
cout << "Can't open database" << endl;
return 1;
}
/* Create a transactional object. */
work W(C);
/* Create SQL UPDATE statement */
sql = "UPDATE COMPANY set SALARY = 25000.00 where ID=1";
/* Execute SQL query */
W.exec( sql );
W.commit();
cout << "Records updated successfully" << endl;
/* Create SQL SELECT statement */
sql = "SELECT * from COMPANY";
/* Create a non-transactional object. */
nontransaction N(C);
/* Execute SQL query */
result R( N.exec( sql ));
/* List down all the records */
for (result::const_iterator c = R.begin(); c != R.end(); ++c) {
cout << "ID = " << c[0].as<int>() << endl;
cout << "Name = " << c[1].as<string>() << endl;
cout << "Age = " << c[2].as<int>() << endl;
cout << "Address = " << c[3].as<string>() << endl;
cout << "Salary = " << c[4].as<float>() << endl;
}
cout << "Operation done successfully" << endl;
C.disconnect ();
} catch (const std::exception &e) {
cerr << e.what() << std::endl;
return 1;
}
return 0;
}
Как только вышеописанная таблица скомпилирована и выполнена, она выдаст следующий результат:
Opened database successfully: testdb Records updated successfully ID = 2 Name = Allen Age = 25 Address = Texas Salary = 15000 ID = 3 Name = Teddy Age = 23 Address = Norway Salary = 20000 ID = 4 Name = Mark Age = 25 Address = Rich-Mond Salary = 65000 ID = 1 Name = Paul Age = 32 Address = California Salary = 25000 Operation done successfully
Операция DELETE
Следующий сегмент кода С показывает, как используется DELETE для удаления каких-либо записей из таблицы COMPANY и отображения оставшихся в таблице записей:
#include <iostream>
#include <pqxx/pqxx>
using namespace std;
using namespace pqxx;
int main(int argc, char* argv[]) {
char * sql;
try {
connection C("dbname = testdb user = postgres password = cohondob \
hostaddr = 127.0.0.1 port = 5432");
if (C.is_open()) {
cout << "Opened database successfully: " << C.dbname() << endl;
} else {
cout << "Can't open database" << endl;
return 1;
}
/* Create a transactional object. */
work W(C);
/* Create SQL DELETE statement */
sql = "DELETE from COMPANY where ID = 2";
/* Execute SQL query */
W.exec( sql );
W.commit();
cout << "Records deleted successfully" << endl;
/* Create SQL SELECT statement */
sql = "SELECT * from COMPANY";
/* Create a non-transactional object. */
nontransaction N(C);
/* Execute SQL query */
result R( N.exec( sql ));
/* List down all the records */
for (result::const_iterator c = R.begin(); c != R.end(); ++c) {
cout << "ID = " << c[0].as<int>() << endl;
cout << "Name = " << c[1].as<string>() << endl;
cout << "Age = " << c[2].as<int>() << endl;
cout << "Address = " << c[3].as<string>() << endl;
cout << "Salary = " << c[4].as<float>() << endl;
}
cout << "Operation done successfully" << endl;
C.disconnect ();
} catch (const std::exception &e) {
cerr << e.what() << std::endl;
return 1;
}
return 0;
}
Как только вышеописанная программа скомпилирована и выполнена, она выдаст следующий результат:
Opened database successfully: testdb Records deleted successfully ID = 3 Name = Teddy Age = 23 Address = Norway Salary = 20000 ID = 4 Name = Mark Age = 25 Address = Rich-Mond Salary = 65000 ID = 1 Name = Paul Age = 32 Address = California Salary = 25000 Operation done successfully



