Partage

[ndb] Interface générique pour SGBD en C++17

Sqlite, MySQL, MongoDB

9 avril 2018 à 1:46:09

Salut !

ndb est une interface générique qui permet de se connecter à n'importe quel moteur de données (SGBD ou autre) Les requêtes sont écrites en C++ et peuvent être exécutées sur différents moteurs de données en changeant un seul paramètre. Les modèles de données sont définis et accessibles compile-time . MySQL et MongoDB sont encore en cours de dev/test.

Tester : https://github.com/ads00/ndb

Features

  • Header only
  • Requêtes full C++ et génériques
  • Support de tout type de moteur de données
  • Expressions SQL générées compile-time
  • Gestion des types personnalisable
  • Accès aux champs via des structures

Exemple

Database (avec macros)

ndb_table(movie,
          ndb_field(id, int, 8),
          ndb_field(name, std::string, 255)
)
ndb_table(music,
          ndb_field(id, int, 8),
          ndb_field(image, std::string, 255)
)

Requêtes

ndb::query<zeta>() << ( movie.id, movie.image ); // get
ndb::query<zeta>() << ( movie.id == a && movie.name == b ); // get all par condition
ndb::query<zeta>() + ( movie.id = 3, movie.name = "test" ); // add
ndb::query<zeta>() - ( movie.id == 3 ); // del

Résultats

for (auto& line : ndb::query<:zeta>() << (movie.id, movie.name) )
{
    std::cout << "\nID : " <<  line[movie.id];
    std::cout << "\nName : " <<  line[movie.name];
}

Minimal

Un exemple avec une base de donnée libray en utilisant le modèle collection et une table movie

#include "my_database.h"

static constexpr const models::collection collection;

int main()
{
    const auto& movie = collection.movie;

    ndb::initializer<sqlite> init;
    ndb::connect<library>();

    ndb::query<library>() + (movie.name = "Interstellar", movie.duration = 2.49_h) );

    return 0;
}

Edit: Ajout de balise html pour afficher le code correctement

-
Edité par ads00 9 avril 2018 à 18:18:40

Vous êtes demandeur·se d'emploi ?
Sans diplôme post-bac ?

Devenez Développeur·se web junior

Je postule
Formation
courte
Financée
à 100%
12 avril 2018 à 5:00:08

Salut,

Je viens d'ajouter la gestion des fonctions paramétrées ou d'expressions dans les requêtes. Ce qui permet de faire :

ndb::query<dbs::zeta>() <<  ( (ndb::now(), ndb::count(movie.id), movie.name) << ndb::limit(2) );

Mais je me demande comment récupérer les résultats sans utiliser les index. Soit je crée un système d'alias pour les champs accessibles via une structure pour le scope actuel. Soit on accède au champs via son expression ce qui donnerait

ndb_alias(count, ndb::count(movie.id), now, ndb::now()); // création de la structure
ndb::query<zeta>() << (alias.now(), alias.count(), movie.name);
line[alias.now]; // accès
ou
ndb::query<zeta>() << (ndb::now(), ndb::count(movie.id), movie.name);
line[now()]; // accès
line[count(movie.id)];

-
Edité par ads00 12 avril 2018 à 5:03:20

4 mai 2018 à 1:28:50

Salut,

Quelques mise à jour pour créer un modèle avec les macros :

ndb_table(movie,
          ndb_field(id, int, 8),
          ndb_field(name, std::string, 255)
)
ndb_table(music,
          ndb_field(id, int, 8),
          ndb_field(image, std::string, 255)
)
// ndb_model([model_name], [tables]...)
ndb_model(library, movie, music)

// ndb_project([project_name], [databases]...)
// ndb_database([database_name], [model_name], [engine])
ndb_project(my_project,
            ndb_database(alpha, library, ndb::sqlite),
            ndb_database(zeta, library, ndb::sqlite)
)



17 mai 2018 à 3:10:56

Salut,

Quelques modifications côté macro et améliorations de la gestion des types.

Voici un exemple complet fonctionnel :

#include <ndb/initializer.hpp>
#include <ndb/engine/sqlite/sqlite.hpp> // engine
#include <ndb/preprocessor.hpp> // database macros
#include <ndb/function.hpp> // ndb::clear
#include <ndb/query.hpp> // query and expression

// database
ndb_table(movie,
           ndb_field_id,
          ndb_field(name, std::string, ndb::size<255>),
          ndb_field(duration, std::chrono::duration<double, std::ratio<3600>>)
)
ndb_table(music,
          ndb_field(id, int),
          ndb_field(image, std::string)
)
ndb_model(library, movie, music)

ndb_project(my_project,
            ndb_database(library, library, ndb::sqlite)
)

/*! Generate constexpr instances usable for query expressions
 * Names are generated in namespaces ndb::models, ndb::tables, ndb::databases::my_project
 *
 * Add _ to the name tu use the type (example : ndb::tables::movie_)
 */

// alias
namespace dbs
{
    using library = ndb::databases::my_project::library_;
}

int main()
{
    using namespace std::chrono_literals;
    const auto& movie = ndb::models::library.movie;

    ndb::initializer<ndb::sqlite> init;
    //! connect to database library
    ndb::connect<dbs::library>();
    //! clear movie table
    ndb::clear<dbs::library>(movie);

    //! add records
    ndb::query<dbs::library>() + (movie.name = "Interstellar", movie.duration = 2.49h);
    ndb::query<dbs::library>() + (movie.name = "Watchmen", movie.duration = 3.30h);

    //! get movie with specified duration
    //! missing informations of the query are deduced compile time
    //! for SQL-like engines, the string is generated compile time
    for (auto& line : ndb::query<dbs::library>() << (movie.duration == 3.30h))
    {
        //! access fields from result using field name
        std::cout << "movie.id : " << line[movie.id] << std::endl;
        std::cout << "movie.name : " << line[movie.name] << std::endl;
        std::cout << "movie.duration : " << line[movie.duration].count() << " Hours" << std::endl;
    }
    return 0;
}



19 mai 2018 à 21:29:58

Salut,

Le modèle génère maintenant des objets qui sont directement utilisable lors des requêtes :

    auto [interstellar] = ndb::oquery<dbs::library>() << (movie.name == "Watchmen");
    std::cout << interstellar.id << " | " << interstellar.name << std::endl;

    for (auto [id, name, duration] : ndb::oquery<dbs::library>() << movie)
    {
        std::cout << "id : " << id << std::endl;
        std::cout << "name : " << name << std::endl;
        std::cout << "name : " << duration.count() << std::endl;
    }



[ndb] Interface générique pour SGBD en C++17

× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
  • Editeur
  • Markdown