QxModel::setModelValue can't set smartpointer to null

Forum for posting problems using QxOrm library

QxModel::setModelValue can't set smartpointer to null

Postby Anubirux » Fri Apr 03, 2020 10:14 am

Hello,

I'm using QxModel to visualise my data but I have some troubles.

I have class which looks like this:
Code: Select all
#include "DbTablesBase.h"

namespace Db {
namespace Tables {

class WarehouseLocation;

using WarehouseLocation_ptr = std::shared_ptr<WarehouseLocation>;
using WarehouseLocation_list = qx::QxCollection<Uuid, WarehouseLocation_ptr>;

class WarehouseLocation : public Base {

  friend struct qx::dao::detail::QxDao_Trigger<Db::Tables::WarehouseLocation>;

public:
  enum Type {
    /* Grupa lokacji.*/
    view = 0,
    /* lokalizacje fizyczne.*/
    internal,
    /* Korekty stanu magazynowego.*/
    inventory,
    /* Dostawy.*/
    procurement,
    /* dostawcy.*/
    supplier,
    /* Klienci.*/
    customer
  };

public:
  QString name;
  Type type;
  WarehouseLocation_ptr parent_location;
  std::optional<QString> description;
  QString path;
  WarehouseLocation_list children_location;

public:
  WarehouseLocation();
  ~WarehouseLocation() override;

  QSqlError fetch_path(QSqlDatabase *pDatabase = nullptr);
  void createPath();

  static QSqlError fetch_all_with_children(WarehouseLocation_list &collection,
    QSqlDatabase *pDatabase = nullptr);

private:

  void onBeforeInsert(qx::dao::detail::IxDao_Helper *dao) override;
  void onBeforeUpdate(qx::dao::detail::IxDao_Helper * dao) override;
};

} // namespace Tables
} // namespace Db

QX_REGISTER_PRIMARY_KEY(Db::Tables::WarehouseLocation, Uuid)
QX_REGISTER_COMPLEX_CLASS_NAME_HPP_EXPORT_DLL(Db::Tables::WarehouseLocation,
  Db::Tables::Base, 0, Db_Tables_WarehouseLocation)

#endif // DBTABLESWAREHOUSELOCATION_H


Setting parent_location using setModelValue with desired id works fine. But when I try bring it to NULL (resting smart pointer) with setModelValue(0, "parent_location", null) I end up in function QxConvert_FromVariant< Uuid >::fromVariant which tries set current value of parent_location-id to null (for uuid its zeros). It messes with following database manipulation because table field parent_location isnt set to null (which it would be if smartpointer would be set to null) but instead filed contains invalid uuid. Writing this post I see some solution cheacking before insert/update which will be clearing relations smartpointers if they contain invalid uuid but I thought that function setModelValue with null value will be able to clear smartpointer by it self. Is there any other better solution or em I missing something?
Anubirux
 
Posts: 3
Joined: Fri Apr 03, 2020 9:46 am

Re: QxModel::setModelValue can't set smartpointer to null

Postby qxorm » Fri Apr 03, 2020 12:25 pm

Hello,

setModelValue(0, "parent_location", null) I end up in function QxConvert_FromVariant< Uuid >::fromVariant

Before going to QxConvert_FromVariant< Uuid >::fromVariant, the code comes from this function (in file ./include/QxConvert/QxConvert_Impl.h) :
Code: Select all
template <typename T>
struct QxConvertHelper_FromVariant<T, qx::cvt::detail::helper::QxConvertHelper_Ptr>
{
   static inline qx_bool fromVariant(const QVariant & v, T & t, const QString & format, int index, qx::cvt::context::ctx_type ctx)
   { if (! t && ! v.isNull()) { qx::trait::construct_ptr<T>::get(t); }; return (t ? qx::cvt::from_variant(v, (* t), format, index, ctx) : qx_bool(false)); }
};


So maybe something is missing here, could you please try to change this function by this (this is not the final solution but just to test it) :
Code: Select all
template <typename T>
struct QxConvertHelper_FromVariant<T, qx::cvt::detail::helper::QxConvertHelper_Ptr>
{
   static inline qx_bool fromVariant(const QVariant & v, T & t, const QString & format, int index, qx::cvt::context::ctx_type ctx)
   { if (! t && ! v.isNull()) { qx::trait::construct_ptr<T>::get(t); } else if (v.isNull()) { t = T(); /* need to create here a qx::trait::reset_ptr<T>::get(t); */ }; return (t ? qx::cvt::from_variant(v, (* t), format, index, ctx) : qx_bool(false)); }
};
qxorm
Site Admin
 
Posts: 481
Joined: Mon Apr 12, 2010 7:45 am

Re: QxModel::setModelValue can't set smartpointer to null

Postby Anubirux » Fri Apr 03, 2020 2:32 pm

Thanks a lot! Now it's working
Anubirux
 
Posts: 3
Joined: Fri Apr 03, 2020 9:46 am

Re: QxModel::setModelValue can't set smartpointer to null

Postby qxorm » Wed Apr 08, 2020 4:20 pm

I have applied the changes in the source code.

So you can download latest version :
- here : https://www.qxorm.com/version/QxOrm_1.4.7_BETA_38.zip
- or on GitHub : https://github.com/QxOrm/QxOrm

Could you please test it ?
qxorm
Site Admin
 
Posts: 481
Joined: Mon Apr 12, 2010 7:45 am

Re: QxModel::setModelValue can't set smartpointer to null

Postby Anubirux » Sat Apr 18, 2020 11:36 am

Hello, sorry for being late but didnt see your request.
Tested and working ;)

BTW I see that I've got 2 more fixes in my copy of your library.

1. Is related to QStringBuilder, and enabled JSON. As I remember I wasnt able to build without this line changed
Code: Select all
void QxRestApi::QxRestApiImpl::buildError(const QSqlError & error)
{
   if (! error.isValid()) { return; }
   m_error = error;
   QJsonObject errJson; QJsonObject errDetail;
   errDetail.insert("code", error.number());
   errDetail.insert(QStringLiteral("desc"), QString(error.driverText() + QLatin1Char('\n') + error.databaseText())); //Here
   errJson.insert("error", errDetail);
   if (! m_requestId.isEmpty()) { errJson.insert("request_id", m_requestId); }
   m_errorJson = errJson;
}


2. QxModelView - here I don't realy remember what was wrong but it has to do something with using QUuid as primary key.
Code: Select all
 static inline void synchronize(qx::IxModel * pModel, T & t)
   {
      if (! pModel) { qAssert(false); return; }
      type_generic_container::clear(t);
      type_collection * pListOfItems = static_cast<type_collection *>(pModel->getCollection());

      for (long l = 0; l < pListOfItems->count(); l++)
      {
         type_ptr ptr = pListOfItems->getByIndex(l); if (! ptr) { continue; }
         type_item item = type_generic_container::createItem();
         type_data & item_val = item.value_qx();
         qx::model_view::detail::QxNestedModel_Helper<type_data, std::is_base_of<QObject, type_data>::value>::synchronize(item_val, (* ptr));
         //FIX
         qx::IxDataMember * pDataMemberId = pModel->m_pDataMemberId;
         if (! pDataMemberId) { qAssert(false); return; }
         QVariant vKey = pDataMemberId->toVariant(ptr.get());
         if (! qx::trait::is_valid_primary_key(vKey)) {
           vKey = QVariant(static_cast<qlonglong>(l));
         }
         qx::cvt::from_variant(vKey, item.key());
         type_generic_container::insertItem(t, item);
      }
   }
Anubirux
 
Posts: 3
Joined: Fri Apr 03, 2020 9:46 am


Return to QxOrm - Help

Who is online

Users browsing this forum: No registered users and 3 guests

cron