Nut/src/tablemodel.cpp

471 lines
12 KiB
C++
Raw Normal View History

2019-02-10 22:11:22 +08:00
/**************************************************************************
2016-05-12 14:08:58 +08:00
**
** This file is part of Nut project.
** https://github.com/HamedMasafi/Nut
**
** Nut is free software: you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Nut is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with Nut. If not, see <http://www.gnu.org/licenses/>.
**
**************************************************************************/
#include <QtCore/QMetaObject>
#include <QtCore/QMetaProperty>
#include <QtCore/QDebug>
#include <QJsonArray>
#include <QJsonObject>
2016-05-21 16:09:03 +08:00
#include "tablemodel.h"
2017-02-01 18:01:21 +08:00
#include "defines.h"
2016-05-12 14:08:58 +08:00
2017-02-01 18:01:21 +08:00
NUT_BEGIN_NAMESPACE
2016-05-12 14:08:58 +08:00
2018-01-16 04:04:42 +08:00
/*
* TODO: It may be good idea if we replace this QSet with two QHash!
* one for className search and another for typeId.
*/
2016-05-21 16:09:03 +08:00
QSet<TableModel*> TableModel::_allModels;
2016-05-12 14:08:58 +08:00
2016-05-21 16:09:03 +08:00
QString TableModel::name() const
2016-05-12 14:08:58 +08:00
{
return _name;
}
2016-05-21 16:09:03 +08:00
void TableModel::setName(const QString &name)
2016-05-12 14:08:58 +08:00
{
_name = name;
}
2016-05-21 16:09:03 +08:00
QString TableModel::className() const
2016-05-12 14:08:58 +08:00
{
return _className;
}
2016-05-21 16:09:03 +08:00
void TableModel::setClassName(const QString &className)
2016-05-12 14:08:58 +08:00
{
_className = className;
}
2016-05-21 16:09:03 +08:00
int TableModel::typeId() const
2016-05-12 14:08:58 +08:00
{
return _typeId;
}
2016-05-21 16:09:03 +08:00
void TableModel::setTypeId(const int &typeId)
2016-05-12 14:08:58 +08:00
{
_typeId = typeId;
}
2018-02-13 23:39:21 +08:00
FieldModel *TableModel::field(int n) const
{
if (n < 0 || n >= _fields.count())
2019-01-09 23:49:50 +08:00
return nullptr;
2018-02-13 23:39:21 +08:00
return _fields.at(n);
}
2019-02-10 22:11:22 +08:00
FieldModel *TableModel::field(const QString &name) const
2016-05-12 14:08:58 +08:00
{
2016-05-21 16:09:03 +08:00
foreach (FieldModel *f, _fields)
2016-05-12 14:08:58 +08:00
if(f->name == name)
return f;
2019-01-09 23:49:50 +08:00
return nullptr;
2016-05-12 14:08:58 +08:00
}
2016-05-21 16:09:03 +08:00
QList<FieldModel *> TableModel::fields() const
2016-05-12 14:08:58 +08:00
{
return _fields;
}
2016-05-21 16:09:03 +08:00
QList<RelationModel *> TableModel::foregionKeys() const
2016-05-12 14:08:58 +08:00
{
2018-02-24 23:43:15 +08:00
return _foreignKeys;
2016-05-12 14:08:58 +08:00
}
2016-05-21 16:09:03 +08:00
QStringList TableModel::fieldsNames() const
2016-05-12 14:08:58 +08:00
{
QStringList ret;
2016-05-21 16:09:03 +08:00
foreach (FieldModel *f, _fields)
2016-05-12 14:08:58 +08:00
ret.append(f->name);
return ret;
}
QSet<TableModel *> TableModel::allModels()
{
return _allModels;
}
2018-01-16 04:04:42 +08:00
/*
* This is not used anywhere
*/
2016-05-21 16:09:03 +08:00
TableModel *TableModel::findByTypeId(int typeId)
2016-05-12 14:08:58 +08:00
{
2016-05-21 16:09:03 +08:00
foreach (TableModel *model, _allModels)
2016-05-12 14:08:58 +08:00
if(model->typeId() == typeId)
return model;
2019-01-09 23:49:50 +08:00
return nullptr;
2016-05-12 14:08:58 +08:00
}
2018-01-16 04:04:42 +08:00
/**
* @brief TableModel::findByClassName
* Find a table model by class name
* @param className
* @return
*/
2019-02-10 22:11:22 +08:00
TableModel *TableModel::findByClassName(const QString &className)
2016-05-12 14:08:58 +08:00
{
2019-01-09 23:49:50 +08:00
foreach (TableModel *model, _allModels){
2016-05-12 14:08:58 +08:00
if(model->className() == className)
return model;
2019-01-09 23:49:50 +08:00
}
2018-01-16 04:04:42 +08:00
2019-01-09 23:49:50 +08:00
return nullptr;
2016-05-12 14:08:58 +08:00
}
2016-05-21 16:09:03 +08:00
bool TableModel::operator ==(const TableModel &t) const{
2016-05-12 14:08:58 +08:00
if(_name != t.name())
return false;
2016-05-21 16:09:03 +08:00
if(fields().count() != t.fields().count())
return false;
foreach (FieldModel *f, _fields) {
FieldModel *tf = t.field(f->name);
2016-05-12 14:08:58 +08:00
if(!tf)
return false;
if(*f != *tf)
return false;
}
return true;
}
2016-05-21 16:09:03 +08:00
bool TableModel::operator !=(const TableModel &t) const
2016-05-12 14:08:58 +08:00
{
return !(*this == t);
}
2018-04-08 23:16:44 +08:00
//bool TableModel::checkClassInfo(const QMetaClassInfo &classInfo,
// QString &type, QString &name, QString &value)
//{
// if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) {
// return false;
// } else {
// QStringList parts = QString(classInfo.value()).split("\n");
// if (parts.count() != 3)
// return false;
// type = parts[0];
// name = parts[1];
// value = parts[2];
// return true;
// }
//}
2018-01-11 17:36:48 +08:00
2019-02-10 22:11:22 +08:00
TableModel::TableModel(int typeId, const QString &tableName)
2016-05-12 14:08:58 +08:00
{
2017-05-28 23:08:59 +08:00
//TODO: check that
// if (findByTypeId(typeId))
// return;
2016-05-12 14:08:58 +08:00
const QMetaObject *tableMetaObject = QMetaType::metaObjectForType(typeId);
_typeId = typeId;
_name = tableName;
_className = tableMetaObject->className();
2017-07-02 22:12:15 +08:00
2017-02-01 18:01:21 +08:00
//#ifdef NUT_NAMESPACE
// if(_className.startsWith(QT_STRINGIFY(NUT_NAMESPACE) "::"))
// _className = _className.replace(QT_STRINGIFY(NUT_NAMESPACE) "::", "");
//#endif
2016-05-12 14:08:58 +08:00
// get fields names
for(int j = 0; j < tableMetaObject->classInfoCount(); j++){
2018-01-11 17:36:48 +08:00
QString type;
QString name;
QString value;
2016-05-12 14:08:58 +08:00
2018-04-08 23:16:44 +08:00
if (!nutClassInfoString(tableMetaObject->classInfo(j),
2018-01-11 17:36:48 +08:00
type, name, value)) {
continue;
}
2016-05-12 14:08:58 +08:00
2018-01-11 17:36:48 +08:00
if(type == __nut_FIELD){
2019-02-10 22:11:22 +08:00
auto *f = new FieldModel;
2018-02-13 23:39:21 +08:00
f->name = f->displayName = name;
2018-01-11 17:36:48 +08:00
_fields.append(f);
2016-05-12 14:08:58 +08:00
}
}
// Browse all fields
for(int j = 1; j < tableMetaObject->propertyCount(); j++){
QMetaProperty fieldProperty = tableMetaObject->property(j);
2016-05-21 16:09:03 +08:00
FieldModel *fieldObj = field(fieldProperty.name());
foreach (FieldModel *f, _fields)
if(f->name == fieldProperty.name())
f = fieldObj;
if(!fieldObj)
2016-05-12 14:08:58 +08:00
continue;
2019-01-21 00:55:32 +08:00
fieldObj->type = static_cast<QMetaType::Type>(fieldProperty.type());
fieldObj->typeName = QString(fieldProperty.typeName());
2016-05-12 14:08:58 +08:00
}
// Browse class infos
for(int j = 0; j < tableMetaObject->classInfoCount(); j++){
2018-01-11 17:36:48 +08:00
QString type;
QString name;
QString value;
2016-05-12 14:08:58 +08:00
2018-04-08 23:16:44 +08:00
if (!nutClassInfoString(tableMetaObject->classInfo(j),
2018-01-11 17:36:48 +08:00
type, name, value)) {
continue;
}
2016-05-12 14:08:58 +08:00
2018-01-11 17:36:48 +08:00
if(type == __nut_FOREGION_KEY){
2019-02-10 22:11:22 +08:00
auto *fk = new RelationModel;
2018-01-13 23:59:55 +08:00
fk->slaveTable = this;
2018-01-15 21:50:40 +08:00
fk->localColumn = name + "Id";
fk->localProperty = name;
2018-02-24 23:43:15 +08:00
fk->foreignColumn = value;
2018-01-13 23:59:55 +08:00
fk->masterClassName = value;
2018-02-24 23:43:15 +08:00
_foreignKeys.append(fk);
2018-01-11 17:36:48 +08:00
}
2016-05-12 14:08:58 +08:00
2018-01-11 17:36:48 +08:00
if(type == __nut_FIELD){
2016-05-12 14:08:58 +08:00
2018-01-11 17:36:48 +08:00
}
FieldModel *f = field(name);
2018-04-08 23:16:44 +08:00
if (!f)
2018-01-11 17:36:48 +08:00
continue;
2018-04-08 23:16:44 +08:00
if (type == __nut_LEN)
2018-01-11 17:36:48 +08:00
f->length = value.toInt();
2018-04-08 23:16:44 +08:00
else if (type == __nut_NOT_NULL)
2018-01-11 17:36:48 +08:00
f->notNull = true;
2018-04-08 23:16:44 +08:00
else if (type == __nut_DEFAULT_VALUE)
2018-01-11 17:36:48 +08:00
f->defaultValue = value;
2018-04-08 23:16:44 +08:00
else if (type == __nut_PRIMARY_KEY)
2018-01-11 17:36:48 +08:00
f->isPrimaryKey = true;
2018-04-08 23:16:44 +08:00
else if (type == __nut_AUTO_INCREMENT)
2018-01-11 17:36:48 +08:00
f->isAutoIncrement = true;
2018-04-08 23:16:44 +08:00
else if (type == __nut_UNIQUE)
2018-01-11 17:36:48 +08:00
f->isUnique = true;
2018-04-08 23:16:44 +08:00
else if (type == __nut_DISPLAY)
2018-02-18 22:58:55 +08:00
f->displayName = value.mid(1, value.length() - 2);
2018-04-08 23:16:44 +08:00
else if (type == __nut_PRIMARY_KEY_AI) {
f->isPrimaryKey = true;
f->isAutoIncrement = true;
}
2016-05-12 14:08:58 +08:00
}
2017-05-28 23:08:59 +08:00
if(!findByTypeId(typeId) && !tableName.isNull())
_allModels.insert(this);
2016-05-12 14:08:58 +08:00
}
/*
"comment": {
"auto_increment": "id",
"fields": {
"id": {
"name": "id",
"type": "int"
},
"userId": {
"name": "userId",
"type": "int"
}
},
"primary_key": "id"
},
*/
2019-02-10 22:11:22 +08:00
TableModel::TableModel(const QJsonObject &json, const QString &tableName) : _typeId(0)
2016-05-12 14:08:58 +08:00
{
_name = tableName;
QJsonObject fields = json.value(__FIELDS).toObject();
2018-02-24 23:43:15 +08:00
QJsonObject relations = json.value(__FOREIGN_KEYS).toObject();
2016-05-12 14:08:58 +08:00
foreach (QString key, fields.keys()) {
QJsonObject fieldObject = fields.value(key).toObject();
2019-02-10 22:11:22 +08:00
auto *f = new FieldModel;
2016-05-12 14:08:58 +08:00
f->name = fieldObject.value(__NAME).toString();
2019-01-21 00:55:32 +08:00
f->type = static_cast<QMetaType::Type>(QMetaType::type(fieldObject.value(__TYPE).toString().toLatin1().data()));
f->typeName = QMetaType::typeName(f->type);
2016-05-12 14:08:58 +08:00
if(fieldObject.contains(__nut_NOT_NULL))
f->notNull = fieldObject.value(__nut_NOT_NULL).toBool();
if(fieldObject.contains(__nut_LEN))
f->length = fieldObject.value(__nut_LEN).toInt();
if(fieldObject.contains(__nut_DEFAULT_VALUE))
f->defaultValue = fieldObject.value(__nut_DEFAULT_VALUE).toString();
_fields.append(f);
}
2018-02-24 23:43:15 +08:00
foreach (QString key, relations.keys()) {
QJsonObject relObject = fields.value(key).toObject();
_foreignKeys.append(new RelationModel(relObject));
}
// if(json.keys().contains(__nut_AUTO_INCREMENT))
// field(json.value(__nut_AUTO_INCREMENT).toString())->isAutoIncrement = true;
2016-05-12 14:08:58 +08:00
2018-02-24 23:43:15 +08:00
// if(json.keys().contains(__nut_PRIMARY_KEY))
// field(json.value(__nut_PRIMARY_KEY).toString())->isAutoIncrement = true;
2016-05-12 14:08:58 +08:00
2017-02-01 18:01:21 +08:00
_allModels.insert(this);
2016-05-12 14:08:58 +08:00
}
2018-03-11 21:13:13 +08:00
TableModel::~TableModel()
{
qDeleteAll(_fields);
qDeleteAll(_foreignKeys);
}
2016-05-21 16:09:03 +08:00
QJsonObject TableModel::toJson() const
2016-05-12 14:08:58 +08:00
{
QJsonObject obj;
QJsonObject fieldsObj;
2018-02-24 23:43:15 +08:00
QJsonObject foreignKeysObj;
2016-05-12 14:08:58 +08:00
2016-05-21 16:09:03 +08:00
foreach (FieldModel *f, _fields) {
2016-05-12 14:08:58 +08:00
QJsonObject fieldObj;
fieldObj.insert(__NAME, f->name);
2017-02-01 18:01:21 +08:00
fieldObj.insert(__TYPE, QString(QVariant::typeToName(f->type)));
2016-05-12 14:08:58 +08:00
if(f->length)
fieldObj.insert(__nut_LEN, f->length);
if(f->notNull)
fieldObj.insert(__nut_NOT_NULL, f->notNull);
if(!f->defaultValue.isNull())
fieldObj.insert(__nut_DEFAULT_VALUE, f->defaultValue);
if(f->isAutoIncrement)
2018-02-24 23:43:15 +08:00
obj.insert(__nut_AUTO_INCREMENT, f->name);
2016-05-12 14:08:58 +08:00
if(f->isPrimaryKey)
2018-02-24 23:43:15 +08:00
obj.insert(__nut_PRIMARY_KEY, f->name);
fieldsObj.insert(f->name, fieldObj);
2016-05-12 14:08:58 +08:00
}
2018-02-24 23:43:15 +08:00
foreach (RelationModel *rel, _foreignKeys)
foreignKeysObj.insert(rel->localColumn, rel->toJson());
2016-05-12 14:08:58 +08:00
obj.insert(__FIELDS, fieldsObj);
2018-02-24 23:43:15 +08:00
obj.insert(__FOREIGN_KEYS, foreignKeysObj);
2016-05-12 14:08:58 +08:00
return obj;
}
2018-02-24 23:43:15 +08:00
RelationModel *TableModel::foregionKey(const QString &otherTable) const
2016-05-12 14:08:58 +08:00
{
2018-02-24 23:43:15 +08:00
foreach (RelationModel *fk, _foreignKeys)
2018-01-13 23:59:55 +08:00
if(fk->masterClassName == otherTable)
2016-05-12 14:08:58 +08:00
return fk;
2019-01-09 23:49:50 +08:00
return nullptr;
2016-05-12 14:08:58 +08:00
}
2018-02-24 23:43:15 +08:00
RelationModel *TableModel::foregionKeyByField(const QString &fieldName) const
{
foreach (RelationModel *fk, _foreignKeys)
if(fk->localColumn == fieldName)
return fk;
2019-01-09 23:49:50 +08:00
return nullptr;
2018-02-24 23:43:15 +08:00
}
2016-05-21 16:09:03 +08:00
QString TableModel::toString() const
2016-05-12 14:08:58 +08:00
{
QStringList sl;
2016-05-21 16:09:03 +08:00
foreach (FieldModel *f, _fields)
2016-05-12 14:08:58 +08:00
sl.append(f->name + " " + QVariant::typeToName(f->type));
QString ret = QString("%1 (%2)")
2019-02-10 22:11:22 +08:00
.arg(_name, sl.join(", "));
2016-05-12 14:08:58 +08:00
return ret;
}
2016-05-21 16:09:03 +08:00
QString TableModel::primaryKey() const
2016-05-12 14:08:58 +08:00
{
2016-05-21 16:09:03 +08:00
foreach (FieldModel *f, _fields)
2016-05-12 14:08:58 +08:00
if(f->isPrimaryKey)
return f->name;
return QString();
2016-05-12 14:08:58 +08:00
}
2017-02-01 18:01:21 +08:00
2018-02-24 23:43:15 +08:00
FieldModel::FieldModel(const QJsonObject &json)
{
name = json.value(__NAME).toString();
2019-01-21 00:55:32 +08:00
type = static_cast<QMetaType::Type>(json.value(__TYPE).toInt());
2018-02-24 23:43:15 +08:00
length = json.value(__nut_LEN).toInt();
notNull = json.value(__nut_NOT_NULL).toBool();
isAutoIncrement = json.value(__nut_AUTO_INCREMENT).toBool();
isPrimaryKey = json.value(__nut_PRIMARY_KEY).toBool();
defaultValue = json.value(__nut_DEFAULT_VALUE).toString();
2018-02-26 18:14:36 +08:00
isUnique = json.value(__nut_UNIQUE).toBool();
2018-02-24 23:43:15 +08:00
}
QJsonObject FieldModel::toJson() const
{
QJsonObject fieldObj;
fieldObj.insert(__NAME, name);
fieldObj.insert(__TYPE, QString(QVariant::typeToName(type)));
fieldObj.insert(__nut_LEN, length);
fieldObj.insert(__nut_NOT_NULL, notNull);
fieldObj.insert(__nut_AUTO_INCREMENT, isAutoIncrement);
fieldObj.insert(__nut_PRIMARY_KEY, isPrimaryKey);
fieldObj.insert(__nut_DEFAULT_VALUE, defaultValue);
return fieldObj;
}
RelationModel::RelationModel(const QJsonObject &obj)
{
localColumn = obj.value("localColumn").toString();
localProperty = obj.value("localProperty").toString();
masterClassName = obj.value("masterClassName").toString();
foreignColumn = obj.value("foreignColumn").toString();
2019-01-09 23:49:50 +08:00
slaveTable = masterTable = nullptr;
2018-02-24 23:43:15 +08:00
}
QJsonObject RelationModel::toJson() const
{
QJsonObject o;
o.insert("localColumn", localColumn);
o.insert("localProperty", localProperty);
o.insert("masterClassName", masterClassName);
o.insert("foreignColumn", foreignColumn);
return o;
}
bool operator ==(const RelationModel &l, const RelationModel &r)
{
return r.foreignColumn == l.foreignColumn
&& r.localColumn == l.localColumn
&& r.localProperty == l.localColumn
&& r.masterClassName == l.masterClassName;
}
bool operator !=(const RelationModel &l, const RelationModel &r)
{
return !(l == r);
}
2017-02-01 18:01:21 +08:00
NUT_END_NAMESPACE