Merge pull request #48 from HamedMasafi/wip/shareddata

Wip/shareddata
This commit is contained in:
Hamed Masafi 2019-07-21 11:43:32 +04:30 committed by GitHub
commit 232eb12355
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 183 additions and 229 deletions

Binary file not shown.

View File

@ -102,14 +102,15 @@ public slots:
Q_PROPERTY(keytype name##Id READ read##Id WRITE write##Id) \ Q_PROPERTY(keytype name##Id READ read##Id WRITE write##Id) \
public: \ public: \
Nut::Row<type> read() const; \ Nut::Row<type> read() const; \
void write(Nut::Row<type> name); \ keytype read##Id() const; \
static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>)& name##Id ## Field(){ \ static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>)& name##Id ## Field(){ \
static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) f = \ static NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) f = \
NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) \ NUT_WRAP_NAMESPACE(FieldPhrase<keytype>) \
(staticMetaObject.className(), #name); \ (staticMetaObject.className(), #name); \
return f; \ return f; \
} \ } \
keytype read##Id() const; \ public slots: \
void write(Nut::Row<type> name); \
void write##Id(keytype name##Id); void write##Id(keytype name##Id);
#define NUT_FOREIGN_KEY_IMPLEMENT(class, type, keytype, name, read, write) \ #define NUT_FOREIGN_KEY_IMPLEMENT(class, type, keytype, name, read, write) \
@ -177,73 +178,69 @@ NUT_BEGIN_NAMESPACE
inline bool nutClassInfo(const QMetaClassInfo &classInfo, inline bool nutClassInfo(const QMetaClassInfo &classInfo,
QString &type, QString &name, QVariant &value) QString &type, QString &name, QVariant &value)
{ {
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) { if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX))
return false; return false;
} else {
QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3)
return false;
type = parts[0]; QStringList parts = QString(classInfo.value()).split("\n");
name = parts[1]; if (parts.count() != 3)
value = qVariantFromValue(parts[2]); return false;
return true;
} type = parts[0];
name = parts[1];
value = qVariantFromValue(parts[2]);
return true;
} }
inline bool nutClassInfoString(const QMetaClassInfo &classInfo, inline bool nutClassInfoString(const QMetaClassInfo &classInfo,
QString &type, QString &name, QString &value) QString &type, QString &name, QString &value)
{ {
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) { if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX))
return false; return false;
} else {
QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3)
return false;
type = parts[0]; QStringList parts = QString(classInfo.value()).split("\n");
name = parts[1]; if (parts.count() != 3)
value = parts[2]; return false;
return true;
} type = parts[0];
name = parts[1];
value = parts[2];
return true;
} }
inline bool nutClassInfoBool(const QMetaClassInfo &classInfo, inline bool nutClassInfoBool(const QMetaClassInfo &classInfo,
QString &type, QString &name, bool &value) QString &type, QString &name, bool &value)
{ {
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) { if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX))
return false; return false;
} else {
QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3)
return false;
QString buffer = parts[2].toLower(); QStringList parts = QString(classInfo.value()).split("\n");
if (buffer != "true" && buffer != "false") if (parts.count() != 3)
return false; return false;
type = parts[0]; QString buffer = parts[2].toLower();
name = parts[1]; if (buffer != "true" && buffer != "false")
value = (buffer == "true"); return false;
return true;
} type = parts[0];
name = parts[1];
value = (buffer == "true");
return true;
} }
inline bool nutClassInfoInt(const QMetaClassInfo &classInfo, inline bool nutClassInfoInt(const QMetaClassInfo &classInfo,
QString &type, QString &name, bool &value) QString &type, QString &name, bool &value)
{ {
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) { if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX))
return false; return false;
} else {
QStringList parts = QString(classInfo.value()).split("\n"); QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3) if (parts.count() != 3)
return false; return false;
bool ok; bool ok;
type = parts[0]; type = parts[0];
name = parts[1]; name = parts[1];
value = parts[2].toInt(&ok); value = parts[2].toInt(&ok);
return ok; return ok;
}
} }
#ifdef NUT_SHARED_POINTER #ifdef NUT_SHARED_POINTER
@ -267,12 +264,12 @@ inline Row<T> create(QObject *parent) {
} }
template<class T> template<class T>
inline T *get(T *row) { inline Row<T> createFrom(T *row) {
return row; return QSharedPointer<T>(row);
} }
template<class T> template<class T>
inline T *get(const QSharedPointer<T> row) { inline Row<T> createFrom(const QSharedPointer<T> row) {
return row.data(); return row;
} }
#else #else
@ -302,32 +299,6 @@ inline T *get(const QSharedPointer<T> row) {
#endif #endif
//template<class C, typename T>
//struct ForeignKeyData {
// Nut::Row<C> _table;
// T _id;
// ForeignKeyData() : _table(nullptr)
// {}
// void setTable(Nut::Row<C> t) {
// _table = t;
// _id = t->primaryValue().value<T>();
// }
// Nut::Row<C> table() const {
// return _table;
// }
// void setValue(const T& val) {
// _table = nullptr;
// _id = val;
// }
// T value() const {
// if (_table)
// return _table->primaryValue().value<T>();
// return _id;
// }
//};
NUT_END_NAMESPACE NUT_END_NAMESPACE
#endif // SYNTAX_DEFINES_H #endif // SYNTAX_DEFINES_H

View File

@ -178,7 +178,7 @@ QString MySqlGenerator::escapeValue(const QVariant &v) const
// } // }
// default: // default:
return SqlGeneratorBase::escapeValue(v); return SqlGeneratorBase::escapeValue(v);
// } // }
} }
@ -306,19 +306,19 @@ QString MySqlGenerator::createConditionalPhrase(const PhraseData *d) const
if (op == PhraseData::AddYears) if (op == PhraseData::AddYears)
return QString("DATE_ADD(%2, INTERVAL %1 YEAR)") return QString("DATE_ADD(%2, INTERVAL %1 YEAR)")
.arg(d->operand.toString(), createConditionalPhrase(d->left)); .arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddMonths) if (op == PhraseData::AddMonths)
return QString("DATE_ADD(%2, INTERVAL %1 MONTH)") return QString("DATE_ADD(%2, INTERVAL %1 MONTH)")
.arg(d->operand.toString(), createConditionalPhrase(d->left)); .arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddDays) if (op == PhraseData::AddDays)
return QString("DATE_ADD(%2, INTERVAL %1 DAY)") return QString("DATE_ADD(%2, INTERVAL %1 DAY)")
.arg(d->operand.toString(), createConditionalPhrase(d->left)); .arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddHours) if (op == PhraseData::AddHours)
return QString("DATE_ADD(%2, INTERVAL %1 HOUR)") return QString("DATE_ADD(%2, INTERVAL %1 HOUR)")
.arg(d->operand.toString(), createConditionalPhrase(d->left)); .arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddMinutes) if (op == PhraseData::AddMinutes)
return QString("DATE_ADD(%2, INTERVAL %1 MINUTE)") return QString("DATE_ADD(%2, INTERVAL %1 MINUTE)")
.arg(d->operand.toString(), createConditionalPhrase(d->left)); .arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddSeconds) if (op == PhraseData::AddSeconds)
return QString("DATE_ADD(%2, INTERVAL %1 SECOND)") return QString("DATE_ADD(%2, INTERVAL %1 SECOND)")
.arg(d->operand.toString(), createConditionalPhrase(d->left)); .arg(d->operand.toString(), createConditionalPhrase(d->left));

View File

@ -29,7 +29,7 @@ NUT_BEGIN_NAMESPACE
class MySqlGenerator : public SqlGeneratorBase class MySqlGenerator : public SqlGeneratorBase
{ {
public: public:
explicit MySqlGenerator(Database *parent = 0); explicit MySqlGenerator(Database *parent = nullptr);
QString fieldType(FieldModel *field) override; QString fieldType(FieldModel *field) override;
QString escapeValue(const QVariant &v) const override; QString escapeValue(const QVariant &v) const override;

View File

@ -344,22 +344,21 @@ QString PostgreSqlGenerator::createConditionalPhrase(const PhraseData *d) const
if (op == PhraseData::AddYears) if (op == PhraseData::AddYears)
return QString("DATEADD(year, %1, %2)") return QString("DATEADD(year, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left)); .arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddMonths) if (op == PhraseData::AddMonths)
return QString("DATEADD(month, %1, %2)") return QString("DATEADD(month, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left)); .arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddDays) if (op == PhraseData::AddDays)
return QString("DATEADD(day, %1, %2)") return QString("DATEADD(day, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left)); .arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddHours) if (op == PhraseData::AddHours)
return QString("DATEADD(hour, %1, %2)") return QString("DATEADD(hour, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left)); .arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddMinutes) if (op == PhraseData::AddMinutes)
return QString("DATEADD(minute, %1, %2)") return QString("DATEADD(minute, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left)); .arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddSeconds) if (op == PhraseData::AddSeconds)
return QString("DATEADD(second, %1, %2)") return QString("DATEADD(second, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left)); .arg(d->operand.toString(), createConditionalPhrase(d->left));
} }
return SqlGeneratorBase::createConditionalPhrase(d); return SqlGeneratorBase::createConditionalPhrase(d);

View File

@ -29,7 +29,7 @@ NUT_BEGIN_NAMESPACE
class PostgreSqlGenerator : public SqlGeneratorBase class PostgreSqlGenerator : public SqlGeneratorBase
{ {
private: private:
bool readInsideParentese(QString &ref, QString &out); bool readInsideParentese(QString &text, QString &out);
bool isPostGisType(const QVariant::Type &t) const; bool isPostGisType(const QVariant::Type &t) const;
public: public:
explicit PostgreSqlGenerator(Database *parent = nullptr); explicit PostgreSqlGenerator(Database *parent = nullptr);

View File

@ -160,7 +160,7 @@ protected:
QString fromTableText(const QString &tableName, QString &joinClassName, QString &orderBy) const; QString fromTableText(const QString &tableName, QString &joinClassName, QString &orderBy) const;
// QString createWhere(QList<WherePhrase> &wheres); // QString createWhere(QList<WherePhrase> &wheres);
void replaceTableNames(QString &command); virtual void replaceTableNames(QString &command);
void removeTableNames(QString &command); void removeTableNames(QString &command);
QString dateTimePartName(const PhraseData::Condition &op) const; QString dateTimePartName(const PhraseData::Condition &op) const;
}; };

View File

@ -167,11 +167,12 @@ QString SqlServerGenerator::escapeValue(const QVariant &v) const
if (mid == QMetaType::QString || mid == QMetaType::QChar) if (mid == QMetaType::QString || mid == QMetaType::QChar)
return "N'" + v.toString() + "'"; return "N'" + v.toString() + "'";
else if (mid == QMetaType::QPoint) { if (mid == QMetaType::QPoint) {
QPoint pt = v.toPoint(); QPoint pt = v.toPoint();
return QString("geography::POINT(%1, %2, 4326)").arg(pt.x()).arg( return QString("geography::POINT(%1, %2, 4326)").arg(pt.x()).arg(
pt.y()); pt.y());
} else if (mid == QMetaType::QPointF) { }
if (mid == QMetaType::QPointF) {
QPointF pt = v.toPointF(); QPointF pt = v.toPointF();
return QString("geography::POINT(%1, %2, 4326)").arg(pt.x()).arg( return QString("geography::POINT(%1, %2, 4326)").arg(pt.x()).arg(
pt.y()); pt.y());

View File

@ -31,15 +31,15 @@ class SqlServerGenerator : public SqlGeneratorBase
public: public:
explicit SqlServerGenerator(Database *parent = nullptr); explicit SqlServerGenerator(Database *parent = nullptr);
QString masterDatabaseName(QString databaseName); QString masterDatabaseName(QString databaseName) override;
QString fieldType(FieldModel *field); QString fieldType(FieldModel *field) override;
QString diff(FieldModel *oldField, FieldModel *newField); QString diff(FieldModel *oldField, FieldModel *newField) override;
QString escapeValue(const QVariant &v) const; QString escapeValue(const QVariant &v) const override;
void appendSkipTake(QString &sql, int skip, int take); void appendSkipTake(QString &sql, int skip, int take) override;
void replaceTableNames(QString &command); // void replaceTableNames(QString &command) override;
}; };

View File

@ -28,15 +28,20 @@ QueryPrivate::QueryPrivate(QueryBase *parent) : q_ptr(parent),
} }
QueryPrivate::~QueryPrivate()
{
}
/*! /*!
* \class Query * \class Query
* \brief This class hold a query. A query can be used for getting database rows, editing or deleting without row fetching. * \brief This class hold a query. A query can be used for getting database rows, editing or deleting without row fetching.
* A query can be used for getting data from database. * A query can be used for getting data from database.
* \code * \code
* auto q = db.posts()->createQuery(); * auto q = db.posts()->query();
* q->join(Post::commentsTable()); * q->join(Post::commentsTable());
* q->orderBy(!Post::saveDateField() & Post::bodyField()); * q->orderBy(!Post::saveDateField() & Post::bodyField());
* q->setWhere(Post::idField() > 5); * q->where(Post::idField() > 5);
* *
* auto posts = q->toList(); * auto posts = q->toList();
* \endcode * \endcode
@ -54,7 +59,7 @@ QueryPrivate::QueryPrivate(QueryBase *parent) : q_ptr(parent),
*/ */
/*! /*!
* \fn Query<T> *Query::setWhere(WherePhrase where) * \fn Query<T> *Query::where(WherePhrase where)
* Where phrase is a phrase using table's static field methods. * Where phrase is a phrase using table's static field methods.
* \code * \code
* q->setWhere(Post::idField() == 4 || Post::titleField().isNull()); * q->setWhere(Post::idField() == 4 || Post::titleField().isNull());

View File

@ -272,14 +272,14 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
// check if key value is changed // check if key value is changed
if (data.lastKeyValue == q.value(data.keyFiledname)) { if (data.lastKeyValue == q.value(data.keyFiledname)) {
--p; --p;
qDebug() << "key os not changed for" << data.keyFiledname; // qDebug() << "key os not changed for" << data.keyFiledname;
continue; continue;
} }
// check if master if current table has processed // check if master if current table has processed
foreach (int m, data.masters) foreach (int m, data.masters)
if (!checked[m]) { if (!checked[m]) {
qDebug() << "row is checked"; // qDebug() << "row is checked";
continue; continue;
} }
@ -288,66 +288,48 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
data.lastKeyValue = q.value(data.keyFiledname); data.lastKeyValue = q.value(data.keyFiledname);
//create table row //create table row
Table *table; Row<Table> row;
Row<T> shp;
if (data.table->className() == d->className) { if (data.table->className() == d->className) {
table = new T(); row = Nut::create<T>();
#ifdef NUT_SHARED_POINTER #ifdef NUT_SHARED_POINTER
shp = QSharedPointer<T>(qobject_cast<T*>(table)); returnList.append(row.objectCast<T>());
returnList.append(shp);
d->tableSet->add(shp);
#else #else
returnList.append(dynamic_cast<T*>(table)); returnList.append(dynamic_cast<T*>(table));
#endif #endif
table->setParentTableSet(d->tableSet); d->tableSet->add(row);
} else { } else {
Table *table;
const QMetaObject *childMetaObject const QMetaObject *childMetaObject
= QMetaType::metaObjectForType(data.table->typeId()); = QMetaType::metaObjectForType(data.table->typeId());
table = qobject_cast<Table *>(childMetaObject->newInstance()); table = qobject_cast<Table *>(childMetaObject->newInstance());
// table = dynamic_cast<Table *>(QMetaType::create(data.table->typeId()));
if (!table) if (!table)
qFatal("Could not create instance of %s", qFatal("Could not create instance of %s",
qPrintable(data.table->name())); qPrintable(data.table->name()));
row = createFrom(table);
} }
QList<FieldModel*> childFields = data.table->fields(); QList<FieldModel*> childFields = data.table->fields();
foreach (FieldModel *field, childFields) foreach (FieldModel *field, childFields)
table->setProperty(field->name.toLatin1().data(), row->setProperty(field->name.toLatin1().data(),
d->database->sqlGenertor()->unescapeValue( d->database->sqlGenertor()->unescapeValue(
field->type, field->type,
q.value(data.table->name() + "." + field->name))); q.value(data.table->name() + "." + field->name)));
for (int i = 0; i < data.masters.count(); ++i) { for (int i = 0; i < data.masters.count(); ++i) {
int master = data.masters[i]; int master = data.masters[i];
#ifdef NUT_SHARED_POINTER
QString mName = QString("set%1").arg(levels[master].lastRow->metaObject()->className());
QString type = QString("Nut::Row<%1>").arg(levels[master].lastRow->metaObject()->className());
bool ok = table->metaObject()->invokeMethod(table,
mName.toLocal8Bit().data(),
QGenericArgument(type.toLatin1().data(), levels[master].lastRow));
#else
bool ok = table->setProperty(data.masterFields[i].toLocal8Bit().data(),
QVariant::fromValue(levels[master].lastRow));
#endif
if (!ok)
qWarning("Unable to set property %s::%s",
table->metaObject()->className(), data.masterFields[i].toLocal8Bit().data());
auto tableset = levels[master].lastRow->childTableSet( auto tableset = levels[master].lastRow->childTableSet(
data.table->className()); data.table->className());
table->setParentTableSet(tableset); tableset->add(row);
#ifdef NUT_SHARED_POINTER
tableset->add(qSharedPointerCast<Table>(shp));
#endif
} }
table->setStatus(Table::FeatchedFromDB); row->setStatus(Table::FeatchedFromDB);
table->setParent(this); row->setParent(this);
table->clear(); row->clear();
//set last created row //set last created row
data.lastRow = /*QSharedPointer<Table>*/(table); data.lastRow = row.data();
} //while } //while
} // while } // while
@ -356,6 +338,7 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
deleteLater(); deleteLater();
#endif #endif
return returnList; return returnList;
} }
template <typename T> template <typename T>

View File

@ -39,7 +39,7 @@ class QueryPrivate : public QSharedData {
public: public:
explicit QueryPrivate(QueryBase *parent); explicit QueryPrivate(QueryBase *parent);
~QueryPrivate() = default; ~QueryPrivate();
QString sql; QString sql;
QString className; QString className;
@ -53,11 +53,6 @@ public:
int take; int take;
PhraseList orderPhrase, fieldPhrase; PhraseList orderPhrase, fieldPhrase;
ConditionalPhrase wherePhrase; ConditionalPhrase wherePhrase;
// QList<WherePhrase> wheres;
// QList<WherePhrase> orderPhrases;
// QList<WherePhrase> fields;
// QHash<QString, QString> orders;
}; };
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -41,7 +41,7 @@ protected:
QExplicitlySharedDataPointer<QueryPrivate> d; QExplicitlySharedDataPointer<QueryPrivate> d;
public: public:
explicit QueryBase(QObject *parent = 0); explicit QueryBase(QObject *parent = nullptr);
protected: protected:
// void addTableToSet(TableSetBase *set, Table *table); // void addTableToSet(TableSetBase *set, Table *table);

View File

@ -44,32 +44,32 @@ NUT_BEGIN_NAMESPACE
*/ */
Table::Table(QObject *parent) : QObject(parent), Table::Table(QObject *parent) : QObject(parent),
d_ptr(new TablePrivate(this)) d(new TablePrivate(this))
{ } { }
Table::~Table() Table::~Table()
{ {
Q_D(Table); //Q_D(Table);
if (d->parentTableSet) // if (d->parentTableSet)
d->parentTableSet->remove(this); // d->parentTableSet->remove(this);
} }
void Table::add(TableSetBase *t) void Table::add(TableSetBase *t)
{ {
Q_D(Table); //Q_D(Table);
d->childTableSets.insert(t); d->childTableSets.insert(t);
} }
//QString Table::primaryKey() const //QString Table::primaryKey() const
//{ //{
// Q_D(const Table); // //Q_D(const Table);
// return d->model->primaryKey(); // return d->model->primaryKey();
//} //}
//bool Table::isPrimaryKeyAutoIncrement() const //bool Table::isPrimaryKeyAutoIncrement() const
//{ //{
// Q_D(const Table); // //Q_D(const Table);
// FieldModel *pk = d->model->field(d->model->primaryKey()); // FieldModel *pk = d->model->field(d->model->primaryKey());
// if (!pk) // if (!pk)
// return false; // return false;
@ -84,7 +84,7 @@ void Table::add(TableSetBase *t)
void Table::propertyChanged(const QString &propName) void Table::propertyChanged(const QString &propName)
{ {
Q_D(Table); //Q_D(Table);
// if (!d->model) // if (!d->model)
// d->model = TableModel::findByClassName(metaObject()->className()); // d->model = TableModel::findByClassName(metaObject()->className());
@ -95,6 +95,7 @@ void Table::propertyChanged(const QString &propName)
// if(f->isPrimaryKey && propName == f->name && f->isAutoIncrement) // if(f->isPrimaryKey && propName == f->name && f->isAutoIncrement)
// return; // return;
d.detach();
d->changedProperties.insert(propName); d->changedProperties.insert(propName);
if (d->status == FeatchedFromDB) if (d->status == FeatchedFromDB)
d->status = Modified; d->status = Modified;
@ -105,25 +106,26 @@ void Table::propertyChanged(const QString &propName)
void Table::setModel(TableModel *model) void Table::setModel(TableModel *model)
{ {
Q_D(Table); //Q_D(Table);
d->model = model; d->model = model;
} }
void Table::clear() void Table::clear()
{ {
Q_D(Table); //Q_D(Table);
d->changedProperties.clear(); d->changedProperties.clear();
} }
QSet<QString> Table::changedProperties() const QSet<QString> Table::changedProperties() const
{ {
Q_D(const Table); //Q_D(const Table);
return d->changedProperties; return d->changedProperties;
} }
bool Table::setParentTable(Table *master, TableModel *masterModel, TableModel *model) bool Table::setParentTable(Table *master, TableModel *masterModel, TableModel *model)
{ {
Q_D(Table); //Q_D(Table);
d.detach();
QString masterClassName = master->metaObject()->className(); QString masterClassName = master->metaObject()->className();
d->refreshModel(); d->refreshModel();
@ -145,22 +147,22 @@ bool Table::setParentTable(Table *master, TableModel *masterModel, TableModel *m
TableSetBase *Table::parentTableSet() const TableSetBase *Table::parentTableSet() const
{ {
Q_D(const Table); //Q_D(const Table);
return d->parentTableSet; return d->parentTableSet;
} }
void Table::setParentTableSet(TableSetBase *parent) void Table::setParentTableSet(TableSetBase *parent)
{ {
Q_D(Table); //Q_D(Table);
d->parentTableSet = parent; d->parentTableSet = parent;
if (parent) // if (parent)
d->parentTableSet->add(this); // d->parentTableSet->add(this);
} }
TableSetBase *Table::childTableSet(const QString &name) const TableSetBase *Table::childTableSet(const QString &name) const
{ {
Q_D(const Table); //Q_D(const Table);
foreach (TableSetBase *t, d->childTableSets) foreach (TableSetBase *t, d->childTableSets)
if (t->childClassName() == name) if (t->childClassName() == name)
return t; return t;
@ -169,7 +171,7 @@ TableSetBase *Table::childTableSet(const QString &name) const
int Table::save(Database *db) int Table::save(Database *db)
{ {
Q_D(Table); //Q_D(Table);
QSqlQuery q = db->exec(db->sqlGenertor()->saveRecord(this, db->tableName(metaObject()->className()))); QSqlQuery q = db->exec(db->sqlGenertor()->saveRecord(this, db->tableName(metaObject()->className())));
@ -186,19 +188,19 @@ int Table::save(Database *db)
Table::Status Table::status() const Table::Status Table::status() const
{ {
Q_D(const Table); //Q_D(const Table);
return static_cast<Status>(d->status); return static_cast<Status>(d->status);
} }
void Table::setStatus(const Status &status) void Table::setStatus(const Status &status)
{ {
Q_D(Table); //Q_D(Table);
d->status = status; d->status = status;
} }
TablePrivate::TablePrivate(Table *parent) : q_ptr(parent), TablePrivate::TablePrivate(Table *parent) : QSharedData(),
model(nullptr), status(Table::NewCreated), parentTableSet(nullptr) model(nullptr), status(Table::NewCreated), parentTableSet(nullptr)
{ {
@ -206,7 +208,7 @@ TablePrivate::TablePrivate(Table *parent) : q_ptr(parent),
void TablePrivate::refreshModel() void TablePrivate::refreshModel()
{ {
Q_Q(Table); // Q_Q(Table);
// if (!model) // if (!model)
// model = TableModel::findByClassName(q->metaObject()->className()); // model = TableModel::findByClassName(q->metaObject()->className());
} }

View File

@ -38,8 +38,7 @@ class TablePrivate;
class NUT_EXPORT Table : public QObject class NUT_EXPORT Table : public QObject
{ {
Q_OBJECT Q_OBJECT
TablePrivate *d_ptr; QExplicitlySharedDataPointer<TablePrivate> d;
Q_DECLARE_PRIVATE(Table)
public: public:
explicit Table(QObject *parentTableSet = nullptr); explicit Table(QObject *parentTableSet = nullptr);

View File

@ -4,13 +4,14 @@
#include "defines.h" #include "defines.h"
#include <QtCore/QSet> #include <QtCore/QSet>
#include <QSharedData>
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
class TableModel; class TableModel;
class Table; class Table;
class TableSetBase; class TableSetBase;
class TablePrivate { class TablePrivate : public QSharedData {
Table *q_ptr; Table *q_ptr;
Q_DECLARE_PUBLIC(Table) Q_DECLARE_PUBLIC(Table)

View File

@ -31,8 +31,7 @@ NUT_BEGIN_NAMESPACE
class TableModel; class TableModel;
struct FieldModel{ struct FieldModel{
explicit FieldModel() : name(QString()), length(0), defaultValue(QString()), explicit FieldModel() : name(QString()), defaultValue(QString())
notNull(false), isPrimaryKey(false), isAutoIncrement(false), isUnique(false)
{ {
} }
@ -42,12 +41,12 @@ struct FieldModel{
QString name; QString name;
QMetaType::Type type; QMetaType::Type type;
QString typeName; QString typeName;
int length; int length{0};
QString defaultValue; QString defaultValue;
bool notNull; bool notNull{false};
bool isPrimaryKey; bool isPrimaryKey{false};
bool isAutoIncrement; bool isAutoIncrement{false};
bool isUnique; bool isUnique{false};
QString displayName; QString displayName;
bool operator ==(const FieldModel &f) const{ bool operator ==(const FieldModel &f) const{
@ -70,18 +69,17 @@ struct FieldModel{
struct RelationModel{ struct RelationModel{
RelationModel() : localColumn(QString()), localProperty(QString()), RelationModel() : localColumn(QString()), localProperty(QString()),
slaveTable(nullptr), foreignColumn(QString()), masterTable(nullptr), slaveTable(nullptr), foreignColumn(QString()), masterClassName(QString())
masterClassName(QString())
{} {}
explicit RelationModel(const QJsonObject &obj); explicit RelationModel(const QJsonObject &obj);
//slave //slave
QString localColumn; QString localColumn;
QString localProperty; QString localProperty;
TableModel *slaveTable; TableModel *slaveTable{nullptr};
//master //master
QString foreignColumn; QString foreignColumn;
TableModel *masterTable; TableModel *masterTable{nullptr};
QString masterClassName; QString masterClassName;

View File

@ -58,8 +58,8 @@ public:
void remove(RowList<T> t); void remove(RowList<T> t);
int length() const; int length() const;
T *at(int i) const; Row<T> at(int i) const;
const T &operator[](int i) const; const Row<T> operator[](int i) const;
Query<T> *query(bool autoDelete = true); Query<T> *query(bool autoDelete = true);
BulkInserter *bulkInserter(); BulkInserter *bulkInserter();
@ -95,20 +95,27 @@ Q_OUTOFLINE_TEMPLATE BulkInserter *TableSet<T>::bulkInserter()
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE int TableSet<T>::length() const Q_OUTOFLINE_TEMPLATE int TableSet<T>::length() const
{ {
return data->tables.count(); return data->childs.count();
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE T *TableSet<T >::at(int i) const Q_OUTOFLINE_TEMPLATE Row<T> TableSet<T >::at(int i) const
{ {
//TODO: check #ifdef NUT_SHARED_POINTER
return reinterpret_cast<T*>(data->childRows.at(i)); return data->childs.at(i).objectCast<T>();
#else
return reinterpret_cast<T*>(data->childs.at(i));
#endif
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE const T &TableSet<T>::operator[](int i) const Q_OUTOFLINE_TEMPLATE const Row<T> TableSet<T>::operator[](int i) const
{ {
return data->childRows[i]; #ifdef NUT_SHARED_POINTER
return data->childs.at(i).objectCast<T>();
#else
return reinterpret_cast<T*>(data->childs.at(i));
#endif
} }
template<class T> template<class T>
@ -116,8 +123,8 @@ Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(Row<T> t)
{ {
data.detach(); data.detach();
data->childs.append(t); data->childs.append(t);
data->tables.insert(t.data()); // data->tables.insert(t.data());
data->childRows.append(t.data()); // data->childRows.append(t.data());
// if (_database) // if (_database)
// t->setModel(_database->model().tableByClassName(t->metaObject()->className())); // t->setModel(_database->model().tableByClassName(t->metaObject()->className()));
@ -138,8 +145,8 @@ template<class T>
Q_OUTOFLINE_TEMPLATE void TableSet<T>::remove(Row<T> t) Q_OUTOFLINE_TEMPLATE void TableSet<T>::remove(Row<T> t)
{ {
data.detach(); data.detach();
data->childs.removeOne(t.data()); // data->childs.removeOne(t.data());
data->tables.remove(t.data()); // data->tables.remove(t.data());
data->childs.removeOne(t); data->childs.removeOne(t);
t->setStatus(Table::Deleted); t->setStatus(Table::Deleted);
} }

View File

@ -40,11 +40,9 @@ TableSetBase::TableSetBase(Table *parent) : QObject(parent),
TableSetBase::~TableSetBase() TableSetBase::~TableSetBase()
{ {
foreach (Table *t, data->tables)
t->setParentTableSet(nullptr);
foreach (Row<Table> t, data->childs) foreach (Row<Table> t, data->childs)
t->setParentTableSet(nullptr); if (t)
t->setParentTableSet(nullptr);
} }
int TableSetBase::save(Database *db, bool cleanUp) int TableSetBase::save(Database *db, bool cleanUp)
@ -54,7 +52,7 @@ int TableSetBase::save(Database *db, bool cleanUp)
if (data->table) if (data->table)
masterModel = db->model().tableByClassName(data->table->metaObject()->className()); masterModel = db->model().tableByClassName(data->table->metaObject()->className());
foreach (Table *t, data->childRows) { foreach (Row<Table> t, data->childs) {
if(data->table) if(data->table)
t->setParentTable(data->table, t->setParentTable(data->table,
masterModel, masterModel,
@ -65,16 +63,16 @@ int TableSetBase::save(Database *db, bool cleanUp)
|| t->status() == Table::Deleted){ || t->status() == Table::Deleted){
rowsAffected += t->save(db); rowsAffected += t->save(db);
if(cleanUp) if(cleanUp)
#ifndef NUT_SHARED_POINTER #ifdef NUT_SHARED_POINTER
t->deleteLater();
#else
remove(t); remove(t);
#else
t->deleteLater();
#endif #endif
} }
} }
if (cleanUp) if (cleanUp)
data->childRows.clear(); data->childs.clear();
return rowsAffected; return rowsAffected;
} }
@ -82,38 +80,23 @@ int TableSetBase::save(Database *db, bool cleanUp)
void TableSetBase::clearChilds() void TableSetBase::clearChilds()
{ {
#ifndef NUT_SHARED_POINTER #ifndef NUT_SHARED_POINTER
foreach (Table *t, data->childRows) foreach (Table *t, data->childs)
t->deleteLater(); t->deleteLater();
#endif #endif
data->childRows.clear(); data->childs.clear();
}
void TableSetBase::add(Table *t)
{
if(!data->tables.contains(get(t))){
data.detach();
data->tables.insert(get(t));
data->childRows.append(get(t));
}
}
void TableSetBase::remove(Table *t)
{
data.detach();
data->tables.remove(get(t));
data->childRows.removeOne(get(t));
} }
void TableSetBase::add(Row<Table> t) void TableSetBase::add(Row<Table> t)
{ {
data.detach(); data.detach();
data->childs.append(t); data->childs.append(t);
t->setParentTableSet(this);
} }
void TableSetBase::remove(Row<Table> t) void TableSetBase::remove(Row<Table> t)
{ {
data.detach(); data.detach();
data->childs.removeOne(t); data->childs.removeAll(t);
} }
QString TableSetBase::childClassName() const QString TableSetBase::childClassName() const

View File

@ -49,17 +49,11 @@ public:
void setDatabase(Database *database); void setDatabase(Database *database);
protected: protected:
// QSet<Table*> _tables;
// RowList<Table> _childRows;
// Database *_database;
// Table *_table;
//// QString _tableName;
// QString _childClassName;
QExplicitlySharedDataPointer<TableSetBaseData> data; QExplicitlySharedDataPointer<TableSetBaseData> data;
public://TODO: change this to private public://TODO: change this to private
void add(Table* t); // void add(Table* t);
void remove(Table *t); // void remove(Table *t);
void add(Row<Table> t); void add(Row<Table> t);
void remove(Row<Table> t); void remove(Row<Table> t);

View File

@ -39,8 +39,8 @@ public:
database(nullptr), table(parent) database(nullptr), table(parent)
{ } { }
QSet<Table*> tables; // QSet<Table*> tables;
QList<Table*> childRows; // QList<Table*> childRows;
RowList<Table> childs; RowList<Table> childs;
Database *database; Database *database;

View File

@ -2,6 +2,7 @@
#define CONSTS_H #define CONSTS_H
#include <qsystemdetection.h> #include <qsystemdetection.h>
#include <qcompilerdetection.h>
#define REGISTER(x) qDebug() << (#x) << "type id:" << qMetaTypeId<x*>() #define REGISTER(x) qDebug() << (#x) << "type id:" << qMetaTypeId<x*>()
#define PRINT(x) #define PRINT(x)
@ -27,6 +28,20 @@
# define OS "Unknown" # define OS "Unknown"
#endif #endif
#ifdef Q_CC_GNU
# ifdef Q_CC_MINGW
# define CC "MinGW"
# else
# define CC "GNU"
# endif
#elif defined (Q_CC_MSVC)
# define CC "msvc"
#elif defined (Q_CC_CLANG)
# define CC "clang"
#else
# define CC "Unknown"
#endif
#define PRINT_FORM(db) \ #define PRINT_FORM(db) \
qDebug() << "\n\n****************************" \ qDebug() << "\n\n****************************" \
<< "\nAll tests passed," \ << "\nAll tests passed," \
@ -34,6 +49,7 @@
<< "hamed.masafi@gmail.com" \ << "hamed.masafi@gmail.com" \
<< "\n\tDriver:" << db.driver() \ << "\n\tDriver:" << db.driver() \
<< "\n\tOS: " OS " (version: ________)" \ << "\n\tOS: " OS " (version: ________)" \
<< "\n\tCompiler: " CC " (version: ________)" \
<< "\n\tQt version: " QT_VERSION_STR \ << "\n\tQt version: " QT_VERSION_STR \
<< "\n\tTest:" << metaObject()->className() \ << "\n\tTest:" << metaObject()->className() \
<< "\n****************************\n"; << "\n****************************\n";