Hosszú kihagyás után újra, a megújult deadlime.project-en először végre kézbe veszem a billentyűzetem és egy (szerintem) érdekes témával folytatom itteni pályafutásom.
Ez a téma nem lenne más, mint a PostgreSQL adatbázis-kezelő elérése C/C++ programokból.\ Az adatbázis eléréséhez a libpq áll a rendelkezésünkre. Próbáltam a libpqxx könyvtárat is, de rengeteg gond volt vele, ezért a "gyártó" által biztosított C-s lib-nél maradtam.
Ha forrásból telepítjük a PgSql-t, vagy windowson a megfelelő helyen pipálunk, akkor azonnal a rendelkezésünkre áll ez a könyvtár. Csak a fordítónak kell megadnunk az elérési utakat. Beállítástól függően #include <libpq-fe.h> vagy #include "libpq-fe.h" formában kell behúzni a forrásfájlunkba.
Nem célom, hogy minden függvényt bemutassak, arra megfelelőbb a PostgreSQL saját dokumentációja. Csupán azokat szeretném megemlíteni, melyek használat közben a legfontosabbak.

Tehát akkor egy kis kód:

#include <iostream>
#include <string>
#include <libpq-fe.h>

int main()
{
    // kapcsolódáshoz szükséges adatok
    const std::string   conninfo = "host=localhost port=5432 dbname=polaa user=polaa password=";
    // a kapcsolatmutató
    PGconn             *conn;
    // az eredménymutató
    PGresult           *res;

    /* kapcsolódás */
    conn = PQconnectdb(conninfo.c_str());
    if (PQstatus(conn) != CONNECTION_OK) 
    {
        std::cout << "Kapcsolódási hiba: " << PQerrorMessage(conn) << std::endl;
        PQfinish(conn);
        return 1;
    }

    /* ... */
}

Először is be kell vezetnünk néhány elengedhetetlen változót. Az adatbázishoz a PGconn *PQconnectdb(const *conninfo) függvénnyel kapcsolódhatunk hasonló módon, mint PHP-ban. A következő ellenőrzés szerintem magáért beszél.
A ConnStatusType PQstatus(const PGconn *conn) függvénnyel a kapcsolat aktuális állapotáról kaphatunk információt.
A void PQfinish(const PGconn *conn) függvény szerepe, hogy lezárja a kapcsolatot és felszabadítsa a PGconn által lefoglalt memóriát.

/* ... */
int main()
{
    /* ... */
    
    /* parancs */
    res = PQexec(conn, "INSERT INTO teszt VALUES (5, 10)");
    if (PQresultStatus(res) != PGRES_COMMAND_OK)
    {
        std::cout << "Parancsvégrehajtási hiba: " << PQerrorMessage(conn) << std::endl;
        PQclear(res);
        PQfinish(conn);
        return 1;
    }
    PQclear(res);
    
    /* ... */
}

A következő fontos függvény a PGresult *PQexec(PGconn *conn, const char *query), mely egy kérést küld a szervernek és egy Pgresult-ban tárolja az eredményt.
Ezt az eredményt a ExecStatusType PQresultStatus(const PGresult *res) függvénnyel ellenőrizhetjük.
A PGresult által lefoglalt memóriát a void PQclear(const PGresult *res) függvénnyel szabadíthatjuk fel. Fontos minden alkalommal meghívni, hogy még véletlenül se maradjon memória szemét hátra a programunk után.

/* ... */
int main()
{
    /* ... */
    
    /* lekérdezés */
    res = PQexec(conn, "SELECT * FROM teszt");
    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
        std::cout << "Lekérdezés hiba: " << PQerrorMessage(conn) << std::endl;
        PQclear(res);
        PQfinish(conn);
        return 1;
    }
    /* lekérdezés feldolgozása */
    int rowNum, fieldNum;
    int i, j;
    
    rowNum      = PQntuples(res);
    fieldNum    = PQnfields(res);
    
    for (i = 0; i < fieldNum; i++)
    {
        std::cout << PQfname(res, i) << "\t";
    }
    std::cout << std::endl;
    
    for (i = 0; i < rowNum; i++)
    {
        for (j = 0; j < fieldNum; j++)
        {
            std::cout << PQgetvalue(res, i, j) << "\t";
        }
        std::cout << std::endl;
    }
    PQclear(res);
    
    PQfinish(conn);
    return 0;
}

A bemutató forrás végére hagytam a lekérdezést. Az eredménytáblában történő navigálást számos függvény könnyíti meg.
A sorok, illetve oszlopok számát az int PQntuples(const PGresult *res), illetve az int PQnfields(const PGresult *res) függvények adják vissza.
Az egyes oszlopok nevét a char *PQfname(const PGresult *res, int field_num) adja meg az oszlop indexe alapján (ami természetesen 0-ról indul). Az egyes mezők tartalmát a char *PQgetvalue(const PGresult *res, int tup_num, int field_num) függvény adja meg a PQfname-hez hasonló módon.

Ezekkel az alapfüggvényekkel már nyugodtan lehet kisebb-nagyobb adatbázis műveleteket végezni. Az objektum-orientált megoldást majd egy következő bejegyzésben részletezem.
A fenti kódot csak windowson próbáltam, mert csak. Fontos megjegyezni, hogy ott a lefordult exe mellé a következő dll-eket kell másolni még a PgSql-ünk bin nevü könyvtárából: comerr32.dll, krb5_32.dll, libiconv-2.dll, libintl-2.dll, libpq.dll.