QString QxClassX::dumpSqlSchema()
{
   qDebug("[QxOrm] qx::QxClassX::dumpSqlSchema() : %s", "be careful with this function, it's just an example and tested only with SQLite database, so it's strongly recommended to write your own function to create your SQL schema");
   QxCollection<QString, IxClass *> * pAllClasses = QxClassX::getAllClasses();
   if (! pAllClasses) { qAssert(false); return ""; }
   QString sql; long lSqlCount = 0;

   for (long k = 0; k < pAllClasses->count(); k++)
   {
      IxClass * pClass = pAllClasses->getByIndex(k);
      if (! pClass) { continue; }

      // If the class is a parameter or a service from 'QxService' module, it's not a persistent class
      if (pClass->isKindOf("qx::service::IxParameter") || pClass->isKindOf("qx::service::IxService")) { continue; }

      // ----
      // Here, you can filter other classes using property bag (meta-data), for example :
      //    QString sProp = pClass->getPropertyBag("NOT_A_DATABASE_OBJECT").toString();
      //    if (sProp == "1") { continue; }
      // ----

      // Get the version of the class : if (version = 0) then 'CREATE TABLE', else if (version > 0) then 'ALTER TABLE'
      long lVersion = pClass->getVersion();
      bool bCreateTable = (lVersion <= 0);
      sql += (bCreateTable ? "CREATE TABLE " : "ALTER TABLE ");
      sql += pClass->getName() + " ";
      sql += (bCreateTable ? "(" : "ADD (");

      // Get the primary key (id) of table, all columns into table, and other parameters associated to table
      IxDataMember * pId = pClass->getId();
      IxDataMemberX * pDataMemberX = pClass->getDataMemberX();
      QxSoftDelete oSoftDelete = pClass->getSoftDelete();

      // Insert primary key (id) to SQL schema
      if (pId && (bCreateTable || (pId->getVersion() >= lVersion)))
      { sql += pId->getSqlNameAndTypeAndParams(", ") + ", "; qAssert(! pId->getSqlType().isEmpty()); }

      // Insert all columns to SQL schema
      for (long l = 0; (pDataMemberX && (l < pDataMemberX->count_WithDaoStrategy())); l++)
      {
         IxDataMember * p = pDataMemberX->get_WithDaoStrategy(l);
         if (isValid_DataMember(p) && (p != pId) && (bCreateTable || (p->getVersion() >= lVersion)))
         { sql += p->getSqlNameAndTypeAndParams(", ") + ", "; qAssert(! p->getSqlType().isEmpty()); }

         // ----
         // Here, you can use property bag (meta-data) to add some SQL features, for example :
         //    QString sProp = p->getPropertyBag("INDEX").toString();
         //    if (sProp == "1") { sql += "CREATE INDEX" + etc...; }
         // ----
      }

      // Insert soft delete behaviour to SQL schema
      if (bCreateTable && ! oSoftDelete.isEmpty())
      { sql += oSoftDelete.buildSqlQueryToCreateTable() + ", "; }

      // Insert all relations to SQL schema
      for (long l = 0; (pDataMemberX && (l < pDataMemberX->count_WithDaoStrategy())); l++)
      {
         IxDataMember * p = pDataMemberX->get_WithDaoStrategy(l);
         QxSqlRelationParams params(0, 0, (& sql), NULL, NULL, NULL);
         if (isValid_SqlRelation(p) && (p != pId) && (bCreateTable || (p->getVersion() >= lVersion)))
         { p->getSqlRelation()->createTable(params); }
      }

      // Terminate SQL schema for current class
      sql = sql.left(sql.count() - 2); // Remove last ", "
      sql += ")\n";
      lSqlCount++;

      // Create extra-table from relations (for example, many-to-many relation needs an extra-table)
      for (long l = 0; (pDataMemberX && (l < pDataMemberX->count_WithDaoStrategy())); l++)
      {
         IxDataMember * p = pDataMemberX->get_WithDaoStrategy(l);
         if (isValid_SqlRelation(p) && (p != pId) && (bCreateTable || (p->getVersion() >= lVersion)))
         {
            QString sqlExtraTable = p->getSqlRelation()->createExtraTable();
            if (sqlExtraTable.isEmpty()) { continue; }
            sql += sqlExtraTable + "\n";
         }
      }
   }

   qDebug("[QxOrm] start dump SQL schema (%ld)", lSqlCount);
   qDebug("%s", qPrintable(sql));
   qDebug("[QxOrm] %s", "end dump SQL schema");

   return sql;
}

bool QxClassX::isValid_DataMember(IxDataMember * p)
{
   return (p && p->getDao() && ! p->hasSqlRelation());
}

bool QxClassX::isValid_SqlRelation(IxDataMember * p)
{
   bool bIsValid = (p && p->getDao() && p->hasSqlRelation());
   if (bIsValid) { p->getSqlRelation()->init(); }
   return bIsValid;
}