PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment préparer des instructions et lier des paramètres dans Postgresql pour C++

Un exemple simple. Cela imprime simplement le nombre d'entrées avec la valeur d'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;
}

La fonction w.prepared() est un peu alambiquée. C'est similaire à une fonction curried(curry) dans haskell, car elle prend un paramètre et renvoie une autre fonction qui à son tour prend un autre paramètre. Ce genre de chose.

La documentation indique :

Comment passer ces paramètres ? C++ n'a pas de bon moyen de vous laisser passer un nombre illimité et variable d'arguments à un appel de fonction, et le compilateur ne sait pas combien vous allez passer. Il y a une astuce pour cela :vous pouvez traiter la valeur que vous récupérez préparée comme une fonction, que vous appelez pour passer un paramètre. Ce que vous obtenez en retour de cet appel est à nouveau le même, vous pouvez donc l'appeler à nouveau pour passer un autre paramètre et ainsi de suite.

Une fois que vous avez passé tous les paramètres de cette manière, vous invoquez l'instruction avec les paramètres en appelant exec sur l'invocation

S'il y a plus de paramètres, utilisez $1 $2 et ainsi de suite dans le prepare fonction.

c.prepare("SELECT id name FROM mytable WHERE id = $1 AND name = $2")

et donner les variables comme

w.prepared("example")(dollar1_var)(dollar2_var).exec()

Un exemple de préparation dynamique

#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;
}

si vous souhaitez gérer d'autres types de données, utilisez cette définition de fonction

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;
}