Page 1 of 1

Insert query

PostPosted: Wed Dec 22, 2010 3:15 pm
by ruddy32
Bonjour,

Lors de l'enregistrement d'un nouvel objet dans une table ayant un id avec autoincrement, l'identifiant de l'objet n'est pas mis à jour.
Est ce un comportement normal ? Ai-je homis quelque chose dans le code source ?
Code: Select all
namespace MySpace {
class MyClass {
QX_REGISTER_FRIEND_CLASS(MySpace::MyClass)
public:
  MyClass(boost::uint32_t id = 0l);
  boost::uint32_t getId() {
    return m_id;
  }
private:
  boost::uint32_t m_id;
};
}

Code: Select all
namespace qx {
template<> void register_class(QxClass<MySpace::MyClass> & t) {
   IxDataMember * pData = NULL;

   t.setName("tab1");
   pData = t.id(&MySpace::MyClass::m_id, "tab1_id");
}
}

namespace MySpace {
MyClass::MyClass(boost::uint32_t id) :
   m_id(id) {
}
}

Code: Select all
MySpace::MyClass v();
qx::dao::insert(v);
// ici m_id vaut toujours 0

Re: Insert query

PostPosted: Wed Dec 22, 2010 3:42 pm
by QxOrm admin
Bonjour,

Ce n'est pas normal, l'identifiant qui vient d'être ajouté en BD doit être valorisé automatiquement par QxOrm.

Quelle est la base de données utilisée : SQLite ? MySql ? Postgres ? Oracle ? Sql Server ?
Qt propose un mécanisme pour savoir si la fonctionnalité est dispo : il faut vérifier que "QSqlDriver::hasFeature" renvoie vrai pour "QSqlDriver::LastInsertId".
De mémoire (je peux me tromper), il me semble que le driver QODBC ne supporte pas ce mécanisme, il faut alors utiliser le driver natif...

Re: Insert query

PostPosted: Wed Dec 22, 2010 4:09 pm
by ruddy32
la base de données utilisée est postgresql. Le processus se déroule dans le contexte d'une transaction.
La fonctionnalité semble bien être supportée car le traitement updateLastInsertId() est bien exécuté car dans le cas présent l'id vaut 2, et il est positionné à 0. Il se peut que le driver QOdbc implémente mal la fonction lastInsertId().

Re: Insert query

PostPosted: Wed Dec 22, 2010 4:18 pm
by ruddy32
Je précise que je suis sous environnement Linux 2.6.

La fonction lastInsertId() renvoi la valeur 0. A prioris c'est la source du problème.
Comment fait-on pour utiliser le driver natif ?

Re: Insert query

PostPosted: Wed Dec 22, 2010 4:31 pm
by ruddy32
Après quelques recherches, il semble que lors d'une transaction cette fonction renvoi toujours la valeur 0. Existe t il une solution à ce problème ?

Re: Insert query

PostPosted: Wed Dec 22, 2010 9:08 pm
by ruddy32
Dois-je utiliser on_after_insert ? Un exemple de mise en oeuvre ?
Merci

Re: Insert query

PostPosted: Thu Dec 23, 2010 9:05 am
by QxOrm admin
Tout d'abord, la base utilisée est PostGres, donc je recommande fortement d'utiliser le driver natif puisqu'il est disponible avec Qt, les performances seront bien meilleures :
Il faut donc utiliser le plugin "QPSQL" à la place du plugin "QODBC".
Si ce plugin est non dispo sur le poste de dév, quelques recherches sur le net pour le compiler ou le télécharger...

Ensuite, après quelques recherches, le driver "QPSQL" supporte correctement la fonctionnalité "LastInsertId".
Par contre, la doc de Qt indique une petite subtilité :
http://doc.qt.nokia.com/latest/qsqlquer ... stInsertId

Note: For this function to work in PSQL, the table table must contain OIDs, which may not have been created by default. Check the default_with_oids configuration variable to be sure.
Donc visiblement il faut paramétrer la table avec des "OIDs".

Enfin, concernant "on_after_insert", c'est un trigger, il en existe plusieurs dans QxOrm.
Je ne pense pas que ce soit la solution au problème mais peut être un moyen de contournement.
Pour l'utiliser, il suffit de spécialiser le template pour une classe donnée : la méthode spécialisée sera alors appelée automatiquement après une insertion en base.

Re: Insert query

PostPosted: Thu Dec 23, 2010 10:45 am
by ruddy32
Merci pour ces renseignements.

Après avoir modifier la structure de la base de données en configurant les tables avec un OID, la fonction renvoi bien une valeur. Mais cette valeur est celle de l'oid et non celle de l'identifiant (serial) de la table.
Doit-on déclarer un ID supplémentaire rattaché à l'OID dans la classe ? Comment fait-on ?

Re: Insert query

PostPosted: Thu Dec 23, 2010 3:14 pm
by QxOrm admin
Je pense que le mieux est de considérer l'OID comme l'identifiant pour l'objet C++.

Il semble qu'il existe un mot clé RETURNING qui pourrait être utilisé avec un INSERT et qui permettrait de récupérer des valeurs après une insertion en base.
Mais c'est du spécifique PostGres et ça nécessite des modifs dans le code de QxOrm, donc ce ne sera pas dispo avant la 1.1.4.

Re: Insert query

PostPosted: Sun Jan 16, 2011 1:53 pm
by QxOrm admin
Avec QxOrm 1.1.4, les Trigger peuvent en effet être une solution pour récupérer le "vrai" identifiant stocké dans la table (et non l'OID).
Exemple de trigger :
http://www.qxorm.com/qxorm_fr/faq.html#faq_130

Dans le cas de PostGres et dans le même esprit que l'exemple de la FAQ, il faut utiliser la fct : onAfterInsert().
Il suffit alors de créer dans cette fonction une requête SQL SELECT pour obtenir le vrai identifiant en fct de l'OID.
Le nom de la table a interroger est disponible grâce au paramètre dao.