PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como preparar instruções e parâmetros de ligação no Postgresql para C++


Um exemplo simples. Isso apenas imprime o número de entradas com valor de id 0.
#include<pqxx/pqxx>
#include<iostream>

int main()
{
    std::string name = "name";
    int id = 0;
    try {
        //established connection to data base
        pqxx::connection c("dbname=mydb user=keutoi");
        pqxx::work w(c);
        //statement template
        c.prepare("example", "SELECT id  FROM mytable WHERE id = $1");
        //invocation as in varible binding
        pqxx::result r = w.prepared("example")(id).exec();
        
        w.commit();
        //result handling for accessing arrays and conversions look at docs
        std::cout << r.size() << std::endl;
    }
    catch(const std::exception &e)
    {
        std::cerr << e.what() << std::endl;
        return 1;
    }
    return 0;
}

A função w.prepared() é um pouco complicada. É semelhante a uma função curried(curry) em haskell, pois recebe um parâmetro e retorna outra função que, por sua vez, recebe outro parâmetro. Aquele tipo de coisa.

A documentação diz:

Como você passa esses parâmetros? C++ não tem uma boa maneira de permitir que você passe um número variável e ilimitado de argumentos para uma chamada de função, e o compilador não sabe quantos você vai passar. Há um truque para isso:você pode tratar o valor que você recebe de volta preparado como uma função, que você chama para passar um parâmetro. O que você recebe de volta dessa chamada é o mesmo novamente, então você pode chamá-lo novamente para passar outro parâmetro e assim por diante.

Depois de passar todos os parâmetros dessa maneira, você invoca a instrução com os parâmetros chamando exec na invocação

Se houver mais parâmetros, use $1 $2 e assim por diante no prepare função.
c.prepare("SELECT id name FROM mytable WHERE id = $1 AND name = $2")

e dê as variáveis ​​como
w.prepared("example")(dollar1_var)(dollar2_var).exec()

Um exemplo para preparação dinâmica
#include<pqxx/pqxx>
#include<iostream>
#include<vector>

//Just give a vector of data you can change the template<int> to any data type
pqxx::prepare::invocation& prep_dynamic(std::vector<int> data, pqxx::prepare::invocation& inv)
{
    for(auto data_val : data)
        inv(data_val);
    return inv;
}

int main()
{
    std::string name = "name";

    //a data array to be used.
    std::vector<int> ids;
    ids.push_back(0);
    ids.push_back(1);

    try {
        pqxx::connection c("dbname=mydb user=keutoi");
        pqxx::work w(c);

        c.prepare("example", "SELECT id  FROM mytable WHERE id = $1 or id = $2");
        pqxx::prepare::invocation w_invocation = w.prepared("example");

        //dynamic array preparation
        prep_dynamic(ids, w_invocation);
        //executing prepared invocation.
        pqxx::result r = w_invocation.exec();

        w.commit();

        std::cout << r.size() << std::endl;
    }
    catch(const std::exception &e)
    {
        std::cerr << e.what() << std::endl;
        return 1;
    }
    return 0;
}

se você quiser lidar com outros tipos de dados, use esta definição de função
template<class T> pqxx::prepare::invocation& prep_dynamic(std::vector<T> data, pqxx::prepare::invocation& inv)
{
    for(auto data_val : data)
        inv(data_val);
    return inv;
}