join progress / pass to home

This commit is contained in:
Hamed Masafi 2018-01-11 19:44:29 +03:30
parent c5e9d5ec2b
commit b3fac0763c
13 changed files with 135 additions and 53 deletions

View File

@ -198,7 +198,7 @@ bool DatabasePrivate::getCurrectScheema()
}
if (type == __nut_TABLE)
tables.insert(name, type);
tables.insert(name, value);
if (type == __nut_DB_VERSION)
currentModel.setVersion(name);
@ -250,7 +250,6 @@ bool DatabasePrivate::checkClassInfo(const QMetaClassInfo &classInfo, QString &t
type = parts[0];
name = parts[1];
value = parts[2];
qDebug() << Q_FUNC_INFO << parts;
return true;
}
}

View File

@ -70,16 +70,15 @@ TableModel *DatabaseModel::tableByName(QString tableName) const
TableModel *DatabaseModel::tableByClassName(QString className) const
{
QStringList l;
for(int i = 0; i < size(); i++){
TableModel *s = at(i);
l.append(s->className());
if(s->className() == className)
return s;
}
// qWarning("Table with class name '%s' not found in model",
// qUtf8Printable(className));
Q_UNREACHABLE();
return 0;
}

View File

@ -71,7 +71,7 @@ public: \
#define NUT_FOREGION_KEY(type, keytype, name, read, write) \
Q_PROPERTY(type* name READ read WRITE write) \
NUT_DECLARE_FIELD(keytype, name##Id, read##Id, write##Id) \
NUT_INFO(__nut_FOREGION_KEY, name, type) \
NUT_INFO(__nut_FOREGION_KEY, name##Id, type) \
type *m_##name; \
public: \
type *read() const { return m_##name ; } \

View File

@ -140,8 +140,8 @@ QString MySqlGenerator::selectCommand(SqlGeneratorBase::AgregateType t, QString
if (take != -1 && skip != -1)
command.append(QString(" LIMIT %1 OFFSET %2")
.arg(skip)
.arg(take));
.arg(take)
.arg(skip));
return command;
}

View File

@ -71,7 +71,8 @@ QString SqlGeneratorBase::masterDatabaseName(QString databaseName)
QString SqlGeneratorBase::createTable(TableModel *table)
{
Q_UNUSED(table);
return "";
}
QString SqlGeneratorBase::saveRecord(Table *t, QString tableName)
@ -95,6 +96,21 @@ QString SqlGeneratorBase::saveRecord(Table *t, QString tableName)
return "";
}
QString SqlGeneratorBase::recordsPhrase(QString className)
{
TableModel *table = _database->model().tableByClassName(className);
if (!table)
return "";
QString ret = "";
foreach (FieldModel *f, table->fields()) {
if (!ret.isEmpty())
ret.append(", ");
ret.append(QString("%1.%2 AS %1_%2").arg(table->name()).arg(f->name));
}
return ret;
}
QString SqlGeneratorBase::fieldDeclare(FieldModel *field)
{
return field->name + " " + fieldType(field) + (field->notNull ? " NOT NULL" : "");
@ -181,13 +197,13 @@ QString SqlGeneratorBase::diff(TableModel *oldTable, TableModel *newTable)
sql = QString("CREATE TABLE %1 \n(%2)").arg(newTable->name()).arg(
columnSql.join(",\n"));
qDebug() << sql;
}
return sql;
}
QString SqlGeneratorBase::join(const QStringList &list, QStringList *order)
{
//TODO: reorder list first!
//TODO: make this ungly code better and bugless :-)
/*
* Known issues:
@ -198,46 +214,50 @@ QString SqlGeneratorBase::join(const QStringList &list, QStringList *order)
return "";
if (list.count() == 1)
return list.first();
return "[" + list.first() + "]";
DatabaseModel model = _database->model();
QStringList clone = list;
QString mainTable = clone.takeFirst();
QString ret = mainTable;
QString ret = "[" + mainTable + "]";
do {
QString table = model.tableByClassName(clone.first())->name();
clone.takeFirst();
RelationModel *rel = model.relationByTableNames(mainTable, table);
if (!clone.count())
break;
QString table = clone.first();// model.tableByClassName(clone.first())->name();
RelationModel *rel = model.relationByClassNames(mainTable, clone.first());
if (rel) {
//mainTable is master of table
ret.append(QString(" INNER JOIN %1 ON %4.%2 = %1.%3")
ret.append(QString(" INNER JOIN [%1] ON %4.%2 = %1.%3")
.arg(table)
.arg(rel->table->primaryKey())
.arg(rel->localColumn)
.arg(mainTable));
if (order != Q_NULLPTR)
order->append(table + "." + rel->localColumn);
order->append(mainTable + "." + rel->table->primaryKey());
} else{
rel = model.relationByTableNames(table, mainTable);
rel = model.relationByClassNames(clone.first(), mainTable);
if (rel) {
// table is master of mainTable
ret.append(QString(" INNER JOIN %1 ON %4.%2 = %1.%3")
ret.append(QString(" INNER JOIN [%1] ON %4.%2 = %1.%3")
.arg(table)
.arg(rel->localColumn)
.arg(rel->table->primaryKey())
.arg(mainTable));
if (order != Q_NULLPTR)
order->append(table + "." + rel->table->primaryKey());
order->append(mainTable + "." + rel->localColumn);
} else {
qInfo("Relation for %s and %s not exists",
qPrintable(table), qPrintable(mainTable));
}
}
clone.takeFirst();
} while (clone.count());
return ret;
@ -389,6 +409,15 @@ QString SqlGeneratorBase::selectCommand(SqlGeneratorBase::AgregateType t,
QStringList joinedOrders;
QString select = agregateText(t, agregateArg);
if (select == "*") {
select = "";
foreach (QString c, joins) {
if (!select.isEmpty())
select.append(", ");
select.append(recordsPhrase(c));
}
}
QString from = join(joins, &joinedOrders);
QString where = createWhere(wheres);
QString orderText = joinedOrders.join(", ");
@ -433,7 +462,8 @@ QString SqlGeneratorBase::createWhere(QList<WherePhrase> &wheres)
void SqlGeneratorBase::replaceTableNames(QString &command)
{
foreach (TableModel *m, TableModel::allModels())
command = command.replace("[" + m->className() + "].", "`" + m->name() + "`.");
command = command
.replace("[" + m->className() + "]", "`" + m->name() + "`");
}
void SqlGeneratorBase::removeTableNames(QString &command)

View File

@ -72,6 +72,8 @@ public:
virtual QString saveRecord(Table *t, QString tableName);
virtual QString recordsPhrase(QString className);
virtual QString insertRecord(Table *t, QString tableName);
virtual QString updateRecord(Table *t, QString tableName);
virtual QString deleteRecord(Table *t, QString tableName);

View File

@ -71,4 +71,19 @@ QString SqliteGenerator::fieldType(FieldModel *field)
return dbType;
}
QString SqliteGenerator::selectCommand(SqlGeneratorBase::AgregateType t,
QString agregateArg,
QList<WherePhrase> &wheres,
QList<WherePhrase> &orders,
QStringList joins, int skip, int take)
{
QString command = SqlGeneratorBase::selectCommand(t, agregateArg, wheres, orders, joins, skip, take);
if (take != -1 && skip != -1)
command.append(QString(" LIMIT %1 OFFSET %2")
.arg(take)
.arg(skip));
return command;
}
NUT_END_NAMESPACE

View File

@ -32,6 +32,11 @@ public:
SqliteGenerator(Database *parent = 0);
QString fieldType(FieldModel *field);
QString selectCommand(AgregateType t, QString agregateArg,
QList<WherePhrase> &wheres,
QList<WherePhrase> &orders,
QStringList joins, int skip, int take);
};
NUT_END_NAMESPACE

View File

@ -122,73 +122,99 @@ Q_OUTOFLINE_TEMPLATE Query<T>::~Query()
template <class T>
Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
{
Q_UNUSED(count);
Q_D(Query);
QList<T*> result;
d->select = "*";
d->joins.prepend(d->className);
qDebug() << "JOINS="<< d->joins;
d->sql = d->database->sqlGenertor()->selectCommand(
SqlGeneratorBase::SelectAll, "", d->wheres, d->orderPhrases,
d->joins, d->skip, d->take);
qDebug() << d->sql;
QSqlQuery q = d->database->exec(d->sql);
struct LevelData{
QString key;
QString className;
QString tableName;
QVariant keyValue;
int typeId;
TableSetBase *tableSet;
Table *lastRow;
};
QVector<LevelData> levels;
QList<T*> returnList;
foreach (QString className, d->joins) {
LevelData data;
data.className = className;
TableModel *m = d->database->model().tableByClassName(className);
if (!m)
qFatal("Model '%s' not found!!!", qPrintable(className));
data.key = m->primaryKey();
if (!m) {
qWarning("Model '%s' not found!!!", qPrintable(className));
return returnList;
}
data.key = m->name() + "_" + m->primaryKey();
data.typeId = m->typeId();
data.keyValue = QVariant();
data.tableSet = 0;
data.tableName = m->name();
levels.append(data);
}
QList<T*> returnList;
while (q.next()) {
for (int i = 0; i < levels.count(); i++) {
LevelData &data = levels[i];
if (!data.tableSet || data.keyValue != q.value(data.key)) {
if (/*!data.tableSet ||*/ data.keyValue != q.value(data.key)) {
data.keyValue = q.value(data.key);
//create table row
Table *childTable;
Table *table;
if (data.className == d->className) {
childTable = new T();
returnList.append(dynamic_cast<T*>(childTable));
table = new T();
table->setTableSet(d->tableSet);
returnList.append(dynamic_cast<T*>(table));
} else {
const QMetaObject *childMetaObject
= QMetaType::metaObjectForType(data.typeId);
childTable = qobject_cast<Table *>(childMetaObject->newInstance());
table = qobject_cast<Table *>(childMetaObject->newInstance());
}
QStringList childFields
= d->database->model().tableByClassName(data.className)->fieldsNames();
foreach (QString field, childFields)
childTable->setProperty(field.toLatin1().data(), q.value(field));
table->setProperty(field.toLatin1().data(),
q.value(data.tableName + "_" + field));
table->setStatus(Table::FeatchedFromDB);
table->setParent(this);
table->clear();
//set last created row
data.lastRow = childTable;
data.lastRow = table;
if (i < levels.count() - 1) {
QSet<TableSetBase *> tableSets = childTable->tableSets;
foreach (TableSetBase *ts, tableSets)
if (ts->childClassName() == levels[i + 1].className)
data.tableSet = ts;
// if (data.className == d->className) {
// data.tableSet = d->tableSet;
// } else
{
QSet<TableSetBase *> tableSets = table->tableSets;
foreach (TableSetBase *ts, tableSets)
if (ts->childClassName() == levels[i + 1].className)
data.tableSet = ts;
if (!data.tableSet)
qWarning() << "Dataset not found for" << data.className;
}
}
if (i) {
// if (!table->tableSet())
table->setTableSet(levels[i - 1].tableSet);
table->setParentTable(levels[i - 1].lastRow);
} else {
// table->setTableSet(d->tableSet);
// data.tableSet = d->tableSet;
}
if (i)
childTable->setTableSet(levels[i - 1].tableSet);
}
}
}

View File

@ -134,7 +134,6 @@ int Table::save(Database *db)
{
QSqlQuery q = db->exec(db->sqlGenertor()->saveRecord(this, db->tableName(metaObject()->className())));
if(status() == Added && isPrimaryKeyAutoIncrement())
setProperty(primaryKey().toLatin1().data(), q.lastInsertId());

View File

@ -157,7 +157,6 @@ bool TableModel::checkClassInfo(const QMetaClassInfo &classInfo,
type = parts[0];
name = parts[1];
value = parts[2];
qDebug() << Q_FUNC_INFO << parts;
return true;
}
}
@ -190,7 +189,6 @@ TableModel::TableModel(int typeId, QString tableName)
continue;
}
qDebug() << "**********" << type << __nut_FIELD << (type == __nut_FIELD);
if(type == __nut_FIELD){
FieldModel *f = new FieldModel;
f->name = name;

View File

@ -14,6 +14,8 @@
#include "post.h"
#include "comment.h"
#define PRINT(x)
//qDebug() << #x "=" << x;
MainTest::MainTest(QObject *parent) : QObject(parent)
{
}
@ -70,6 +72,7 @@ void MainTest::createPost()
Comment *comment = new Comment;
comment->setMessage("comment #" + QString::number(i));
comment->setSaveDate(QDateTime::currentDateTime());
comment->setAuthorId(user->id());
newPost->comments()->append(comment);
}
db.saveChanges();
@ -106,18 +109,16 @@ void MainTest::createPost2()
void MainTest::selectPosts()
{
auto q = db.posts()->query()
// q->join(Post::commentsTable());
// q->join(Post::commentsTable());
// ->join<User>()
->join<Comment>()
->orderBy(!Post::saveDateField() & Post::bodyField())
->setWhere(Post::idField() == postId);
auto posts = q->toList();
qDebug() << "SQL="<<q->sqlCommand();
post = posts.at(0);
post->setBody("");
PRINT(posts.length());
PRINT(posts.at(0)->comments()->length());
QTEST_ASSERT(posts.length() == 1);
QTEST_ASSERT(posts.at(0)->comments()->length() == 3);
QTEST_ASSERT(posts.at(0)->title() == "post title");
@ -128,12 +129,18 @@ void MainTest::selectPosts()
db.cleanUp();
}
void MainTest::selectFirst()
{
auto posts = db.posts()->query()
->first();
QTEST_ASSERT(posts != Q_NULLPTR);
}
void MainTest::selectPostsWithoutTitle()
{
auto q = db.posts()->query();
q->setWhere(Post::titleField().isNull());
auto count = q->count();
qDebug() << q->sqlCommand();
QTEST_ASSERT(count == 0);
}
@ -169,12 +176,13 @@ void MainTest::join()
{
auto q = db.comments()->query()
->join<User>()
->join<Post>()
->setWhere(Comment::saveDateField() < QDateTime::currentDateTime().addDays(-1))
->orderBy(Comment::saveDateField());
->join<Post>();
q->toList();
Comment *comment = q->first();
// Comment *comment = q->toList().first();
qDebug() << q->sqlCommand();
QTEST_ASSERT(comment->author()->username() == "admin");
}
@ -208,6 +216,7 @@ void MainTest::modifyPost()
->setWhere(Post::idField() == postId);
post = q->first();
PRINT(post->title());
QTEST_ASSERT(post->title() == "new name");
}
@ -215,7 +224,6 @@ void MainTest::emptyDatabase()
{
auto commentsCount = db.comments()->query()->remove();
auto postsCount = db.posts()->query()->remove();
QTEST_ASSERT(postsCount == 3);
QTEST_ASSERT(commentsCount == 6);
}

View File

@ -28,10 +28,11 @@ private slots:
void createPost();
void createPost2();
void selectPosts();
void selectFirst();
void join();
void selectPostsWithoutTitle();
void selectPostIds();
void testDate();
void join();
void selectWithInvalidRelation();
void select10NewstPosts();
void modifyPost();