예제 #1
0
Query::Condition PartTypeHelper::conditionFromFqNames(const QStringList &fqNames)
{
    Query::Condition c;
    c.setSubQueryMode(Query::Or);
    Q_FOREACH (const QString &fqName, fqNames) {
        c.addCondition(conditionFromFqName(fqName));
    }
예제 #2
0
bool RelationFetch::parseStream()
{
    Protocol::FetchRelationsCommand cmd(m_command);

    SelectQueryBuilder<Relation> relationQuery;
    if (cmd.side() > 0) {
        Query::Condition c;
        c.setSubQueryMode(Query::Or);
        c.addValueCondition(Relation::leftIdFullColumnName(), Query::Equals, cmd.side());
        c.addValueCondition(Relation::rightIdFullColumnName(), Query::Equals, cmd.side());
        relationQuery.addCondition(c);
    } else {
        if (cmd.left() > 0) {
            relationQuery.addValueCondition(Relation::leftIdFullColumnName(), Query::Equals, cmd.left());
        }
        if (cmd.right() > 0) {
            relationQuery.addValueCondition(Relation::rightIdFullColumnName(), Query::Equals, cmd.right());
        }
    }
    if (!cmd.types().isEmpty()) {
        relationQuery.addJoin(QueryBuilder::InnerJoin, RelationType::tableName(), Relation::typeIdFullColumnName(), RelationType::idFullColumnName());
        QStringList types;
        types.reserve(cmd.types().size());
        Q_FOREACH (const QByteArray &type, cmd.types()) {
            types << QString::fromUtf8(type);
        }
        relationQuery.addValueCondition(RelationType::nameFullColumnName(), Query::In, types);
    }
예제 #3
0
Query::Condition PartTypeHelper::conditionFromFqName(const QString &fqName)
{
    const QPair<QString, QString> p = parseFqName(fqName);
    Query::Condition c;
    c.setSubQueryMode(Query::And);
    c.addValueCondition(PartType::nsFullColumnName(), Query::Equals, p.first);
    c.addValueCondition(PartType::nameFullColumnName(), Query::Equals, p.second);
    return c;
}
예제 #4
0
파일: datastore.cpp 프로젝트: KDE/akonadi
    Q_FOREACH (const Flag &flag, flags) {
        QSet<PimItem::Id> existing;
        if (checkIfExists) {
            QueryBuilder qb(PimItemFlagRelation::tableName(), QueryBuilder::Select);
            Query::Condition cond;
            cond.addValueCondition(PimItemFlagRelation::rightColumn(), Query::Equals, flag.id());
            cond.addValueCondition(PimItemFlagRelation::leftColumn(), Query::In, itemsIds);
            qb.addColumn(PimItemFlagRelation::leftColumn());
            qb.addCondition(cond);

            if (!qb.exec()) {
                qCDebug(AKONADISERVER_LOG) << "Failed to execute query:" << qb.query().lastError();
                return false;
            }

            QSqlQuery query = qb.query();
            if (query.driver()->hasFeature(QSqlDriver::QuerySize)) {
                //The query size feature is not suppoerted by the sqllite driver
                if (query.size() == items.count()) {
                    continue;
                }
                setBoolPtr(flagsChanged, true);
            }

            while (query.next()) {
                existing << query.value(0).value<PimItem::Id>();
            }
            if (!query.driver()->hasFeature(QSqlDriver::QuerySize)) {
                if (existing.size() != items.count()) {
                    setBoolPtr(flagsChanged, true);
                }
            }
        }

        if (!doAppendItemsFlag(items, flag, existing, col, silent)) {
            return false;
        }
    }
예제 #5
0
파일: datastore.cpp 프로젝트: KDE/akonadi
bool DataStore::setItemsFlags(const PimItem::List &items, const QVector<Flag> &flags,
                              bool *flagsChanged, const Collection &col_, bool silent)
{
    QSet<QByteArray> removedFlags;
    QSet<QByteArray> addedFlags;
    QVariantList insIds;
    QVariantList insFlags;
    Query::Condition delConds(Query::Or);
    Collection col = col_;

    setBoolPtr(flagsChanged, false);

    for (const PimItem &item : items) {
        const Flag::List itemFlags = item.flags();
        Q_FOREACH (const Flag &flag, itemFlags) {
            if (!flags.contains(flag)) {
                removedFlags << flag.name().toLatin1();
                Query::Condition cond;
                cond.addValueCondition(PimItemFlagRelation::leftFullColumnName(), Query::Equals, item.id());
                cond.addValueCondition(PimItemFlagRelation::rightFullColumnName(), Query::Equals, flag.id());
                delConds.addCondition(cond);
            }
        }

        Q_FOREACH (const Flag &flag, flags) {
            if (!itemFlags.contains(flag)) {
                addedFlags << flag.name().toLatin1();
                insIds << item.id();
                insFlags << flag.id();
            }
        }

        if (col.id() == -1) {
            col.setId(item.collectionId());
        } else if (col.id() != item.collectionId()) {
            col.setId(-2);
        }
    }

    if (!removedFlags.empty()) {
        QueryBuilder qb(PimItemFlagRelation::tableName(), QueryBuilder::Delete);
        qb.addCondition(delConds);
        if (!qb.exec()) {
            return false;
        }
    }

    if (!addedFlags.empty()) {
        QueryBuilder qb2(PimItemFlagRelation::tableName(), QueryBuilder::Insert);
        qb2.setColumnValue(PimItemFlagRelation::leftColumn(), insIds);
        qb2.setColumnValue(PimItemFlagRelation::rightColumn(), insFlags);
        qb2.setIdentificationColumn(QString());
        if (!qb2.exec()) {
            return false;
        }
    }

    if (!silent && (!addedFlags.isEmpty() || !removedFlags.isEmpty())) {
        mNotificationCollector->itemsFlagsChanged(items, addedFlags, removedFlags, col);
    }

    setBoolPtr(flagsChanged, (addedFlags != removedFlags));

    return true;
}
예제 #6
0
void QueryBuilderTest::testQueryBuilder_data()
{
    qRegisterMetaType<QVector<QVariant> >();
    mBuilders.clear();
    QTest::addColumn<int>("qbId");
    QTest::addColumn<QString>("sql");
    QTest::addColumn<QVector<QVariant> >("bindValues");

    QueryBuilder qb("table", QueryBuilder::Select);
    qb.addColumn("col1");
    mBuilders << qb;
    QTest::newRow("simple select") << mBuilders.count() << QString("SELECT col1 FROM table") << QVector<QVariant>();

    qb.addColumn("col2");
    mBuilders << qb;
    QTest::newRow("simple select 2") << mBuilders.count() << QString("SELECT col1, col2 FROM table") << QVector<QVariant>();

    qb.addValueCondition("col1", Query::Equals, QVariant(5));
    QVector<QVariant> bindVals;
    bindVals << QVariant(5);
    mBuilders << qb;
    QTest::newRow("single where") << mBuilders.count() << QString("SELECT col1, col2 FROM table WHERE ( col1 = :0 )") << bindVals;

    qb.addColumnCondition("col1", Query::LessOrEqual, "col2");
    mBuilders << qb;
    QTest::newRow("flat where") << mBuilders.count() << QString("SELECT col1, col2 FROM table WHERE ( col1 = :0 AND col1 <= col2 )") << bindVals;

    qb.setSubQueryMode(Query::Or);
    mBuilders << qb;
    QTest::newRow("flat where 2") << mBuilders.count() << QString("SELECT col1, col2 FROM table WHERE ( col1 = :0 OR col1 <= col2 )") << bindVals;

    Condition subCon;
    subCon.addColumnCondition("col1", Query::Greater, "col2");
    subCon.addValueCondition("col1", Query::NotEquals, QVariant());
    qb.addCondition(subCon);
    mBuilders << qb;
    QTest::newRow("hierarchical where") << mBuilders.count() << QString("SELECT col1, col2 FROM table WHERE ( col1 = :0 OR col1 <= col2 OR ( col1 > col2 AND col1 <> NULL ) )") << bindVals;

    qb = QueryBuilder("table");
    qb.addAggregation("col1", "count");
    mBuilders << qb;
    QTest::newRow("single aggregation") << mBuilders.count() << QString("SELECT count(col1) FROM table") << QVector<QVariant>();

    qb = QueryBuilder("table");
    qb.addColumn("col1");
    qb.addSortColumn("col1");
    mBuilders << qb;
    QTest::newRow("single order by") << mBuilders.count() << QString("SELECT col1 FROM table ORDER BY col1 ASC") << QVector<QVariant>();

    qb.addSortColumn("col2", Query::Descending);
    mBuilders << qb;
    QTest::newRow("multiple order by") << mBuilders.count() << QString("SELECT col1 FROM table ORDER BY col1 ASC, col2 DESC") << QVector<QVariant>();

    qb = QueryBuilder("table");
    qb.addColumn("col1");
    QStringList vals;
    vals << "a" << "b" << "c";
    qb.addValueCondition("col1", Query::In, vals);
    bindVals.clear();
    bindVals << QString("a") << QString("b") << QString("c");
    mBuilders << qb;
    QTest::newRow("where in") << mBuilders.count() << QString("SELECT col1 FROM table WHERE ( col1 IN ( :0, :1, :2 ) )") << bindVals;

    qb = QueryBuilder("table", QueryBuilder::Select);
    qb.setDatabaseType(DbType::MySQL);
    qb.addColumn("col1");
    qb.setLimit(1);
    mBuilders << qb;
    QTest::newRow("SELECT with LIMIT") << mBuilders.count() << QString("SELECT col1 FROM table LIMIT 1") << QVector<QVariant>();

    qb = QueryBuilder("table", QueryBuilder::Update);
    qb.setColumnValue("col1", QString("bla"));
    bindVals.clear();
    bindVals << QString("bla");
    mBuilders << qb;
    QTest::newRow("update") << mBuilders.count() << QString("UPDATE table SET col1 = :0") << bindVals;

    qb = QueryBuilder("table1", QueryBuilder::Update);
    qb.setDatabaseType(DbType::MySQL);
    qb.addJoin(QueryBuilder::InnerJoin, "table2", "table1.id", "table2.id");
    qb.addJoin(QueryBuilder::InnerJoin, "table3", "table1.id", "table3.id");
    qb.setColumnValue("col1", QString("bla"));
    bindVals.clear();
    bindVals << QString("bla");
    mBuilders << qb;
    QTest::newRow("update multi table MYSQL") << mBuilders.count() << QString("UPDATE table1, table2, table3 SET col1 = :0 WHERE ( ( table1.id = table2.id ) AND ( table1.id = table3.id ) )")
                                              << bindVals;

    qb = QueryBuilder("table1", QueryBuilder::Update);
    qb.setDatabaseType(DbType::PostgreSQL);
    qb.addJoin(QueryBuilder::InnerJoin, "table2", "table1.id", "table2.id");
    qb.addJoin(QueryBuilder::InnerJoin, "table3", "table1.id", "table3.id");
    qb.setColumnValue("col1", QString("bla"));
    mBuilders << qb;
    QTest::newRow("update multi table PSQL") << mBuilders.count() << QString("UPDATE table1 SET col1 = :0 FROM table2 JOIN table3 WHERE ( ( table1.id = table2.id ) AND ( table1.id = table3.id ) )")
                                             << bindVals;
    ///TODO: test for subquery in SQLite case

    qb = QueryBuilder("table", QueryBuilder::Insert);
    qb.setColumnValue("col1", QString("bla"));
    mBuilders << qb;
    QTest::newRow("insert single column") << mBuilders.count() << QString("INSERT INTO table (col1) VALUES (:0)") << bindVals;

    qb = QueryBuilder("table", QueryBuilder::Insert);
    qb.setColumnValue("col1", QString("bla"));
    qb.setColumnValue("col2", 5);
    bindVals << 5;
    mBuilders << qb;
    QTest::newRow("insert multi column") << mBuilders.count() << QString("INSERT INTO table (col1, col2) VALUES (:0, :1)") << bindVals;

    qb = QueryBuilder("table", QueryBuilder::Insert);
    qb.setDatabaseType(DbType::PostgreSQL);
    qb.setColumnValue("col1", QString("bla"));
    qb.setColumnValue("col2", 5);
    mBuilders << qb;
    QTest::newRow("insert multi column PSQL") << mBuilders.count() << QString("INSERT INTO table (col1, col2) VALUES (:0, :1) RETURNING id") << bindVals;

    qb.setIdentificationColumn(QString());
    mBuilders << qb;
    QTest::newRow("insert multi column PSQL without id") << mBuilders.count() << QString("INSERT INTO table (col1, col2) VALUES (:0, :1)") << bindVals;

    // test GROUP BY foo
    bindVals.clear();
    qb = QueryBuilder("table", QueryBuilder::Select);
    qb.addColumn("foo");
    qb.addGroupColumn("id1");
    mBuilders << qb;
    QTest::newRow("select group by single column") << mBuilders.count() << QString("SELECT foo FROM table GROUP BY id1") << bindVals;
    // test GROUP BY foo, bar
    qb.addGroupColumn("id2");
    mBuilders << qb;
    QTest::newRow("select group by two columns") << mBuilders.count() << QString("SELECT foo FROM table GROUP BY id1, id2") << bindVals;
    // test: HAVING .addValueCondition()
    qb.addValueCondition("bar", Equals, 1, QueryBuilder::HavingCondition);
    mBuilders << qb;
    bindVals << 1;
    QTest::newRow("select with having valueCond") << mBuilders.count() << QString("SELECT foo FROM table GROUP BY id1, id2 HAVING ( bar = :0 )") << bindVals;
    // test: HAVING .addColumnCondition()
    qb.addColumnCondition("asdf", Equals, "yxcv", QueryBuilder::HavingCondition);
    mBuilders << qb;
    QTest::newRow("select with having columnCond") << mBuilders.count() << QString("SELECT foo FROM table GROUP BY id1, id2 HAVING ( bar = :0 AND asdf = yxcv )") << bindVals;
    // test: HAVING .addCondition()
    qb.addCondition(subCon, QueryBuilder::HavingCondition);
    mBuilders << qb;
    QTest::newRow("select with having condition") << mBuilders.count() << QString("SELECT foo FROM table GROUP BY id1, id2 HAVING ( bar = :0 AND asdf = yxcv AND ( col1 > col2 AND col1 <> NULL ) )") << bindVals;
    // test: HAVING and WHERE
    qb.addValueCondition("bla", Equals, 2, QueryBuilder::WhereCondition);
    mBuilders << qb;
    bindVals.clear();
    bindVals << 2 << 1;
    QTest::newRow("select with having and where") << mBuilders.count() << QString("SELECT foo FROM table WHERE ( bla = :0 ) GROUP BY id1, id2 HAVING ( bar = :1 AND asdf = yxcv AND ( col1 > col2 AND col1 <> NULL ) )") << bindVals;

    {
        /// SELECT with JOINS
        QueryBuilder qbTpl = QueryBuilder("table1", QueryBuilder::Select);
        qbTpl.setDatabaseType(DbType::MySQL);
        qbTpl.addColumn("col");
        bindVals.clear();

        QueryBuilder qb = qbTpl;
        qb.addJoin(QueryBuilder::InnerJoin, "table2", "table2.t1_id", "table1.id");
        qb.addJoin(QueryBuilder::LeftJoin, "table3", "table1.id", "table3.t1_id");
        mBuilders << qb;
        QTest::newRow("select left join and inner join (different tables)") << mBuilders.count()
                                                                            << QString("SELECT col FROM table1 INNER JOIN table2 ON ( table2.t1_id = table1.id ) LEFT JOIN table3 ON ( table1.id = table3.t1_id )") << bindVals;

        qb = qbTpl;
        qb.addJoin(QueryBuilder::InnerJoin, "table2", "table2.t1_id", "table1.id");
        qb.addJoin(QueryBuilder::LeftJoin, "table2", "table2.t1_id", "table1.id");
        mBuilders << qb;
        // join-condition too verbose but should not have any impact on speed
        QTest::newRow("select left join and inner join (same table)") << mBuilders.count()
                                                                      << QString("SELECT col FROM table1 INNER JOIN table2 ON ( table2.t1_id = table1.id AND ( table2.t1_id = table1.id ) )") << bindVals;

        // order of joins in the query should be the same as we add the joins in code
        qb = qbTpl;
        qb.addJoin(QueryBuilder::InnerJoin, "b_table", "b_table.t1_id", "table1.id");
        qb.addJoin(QueryBuilder::InnerJoin, "a_table", "a_table.b_id", "b_table.id");
        mBuilders << qb;
        QTest::newRow("select join order") << mBuilders.count()
                                           << QString("SELECT col FROM table1 INNER JOIN b_table ON ( b_table.t1_id = table1.id ) INNER JOIN a_table ON ( a_table.b_id = b_table.id )") << bindVals;
    }

    {
        /// SELECT with CASE
        QueryBuilder qbTpl = QueryBuilder("table1", QueryBuilder::Select);
        qbTpl.setDatabaseType(DbType::MySQL);

        QueryBuilder qb = qbTpl;
        qb.addColumn("col");
        qb.addColumn(Query::Case("col1", Query::Greater, 42, "1", "0"));
        bindVals.clear();
        bindVals << 42;
        mBuilders << qb;
        QTest::newRow("select case simple") << mBuilders.count()
                                            << QString("SELECT col, CASE WHEN ( col1 > :0 ) THEN 1 ELSE 0 END FROM table1") << bindVals;

        qb = qbTpl;
        qb.addAggregation("table1.col1", "sum");
        qb.addAggregation("table1.col2", "count");
        Query::Condition cond(Query::Or);
        cond.addValueCondition("table3.col2", Query::Equals, "value1");
        cond.addValueCondition("table3.col2", Query::Equals, "value2");
        Query::Case caseStmt(cond, "1", "0");
        qb.addAggregation(caseStmt, "sum");
        qb.addJoin(QueryBuilder::LeftJoin, "table2", "table1.col3", "table2.col1");
        qb.addJoin(QueryBuilder::LeftJoin, "table3", "table2.col2", "table3.col1");
        bindVals.clear();
        bindVals << QString("value1") << QString("value2");
        mBuilders <<qb;
        QTest::newRow("select case, aggregation and joins") << mBuilders.count()
                                                            << QString("SELECT sum(table1.col1), count(table1.col2), sum(CASE WHEN ( table3.col2 = :0 OR table3.col2 = :1 ) THEN 1 ELSE 0 END) "
                                                                       "FROM table1 "
                                                                       "LEFT JOIN table2 ON ( table1.col3 = table2.col1 ) "
                                                                       "LEFT JOIN table3 ON ( table2.col2 = table3.col1 )")
                                                            << bindVals;
    }

    {
        /// UPDATE with INNER JOIN
        QueryBuilder qbTpl = QueryBuilder("table1", QueryBuilder::Update);
        qbTpl.setColumnValue("col", 42);
        qbTpl.addJoin(QueryBuilder::InnerJoin, "table2", "table2.t1_id", "table1.id");
        qbTpl.addValueCondition("table2.answer", NotEquals, "foo");
        bindVals.clear();
        bindVals << QVariant(42) << QVariant("foo");

        qb = qbTpl;
        qb.setDatabaseType(DbType::MySQL);
        mBuilders << qb;
        QTest::newRow("update inner join MySQL") << mBuilders.count()
                                                 << QString("UPDATE table1, table2 SET col = :0 WHERE ( table2.answer <> :1 AND ( table2.t1_id = table1.id ) )") << bindVals;

        qb = qbTpl;
        qb.setDatabaseType(DbType::PostgreSQL);
        mBuilders << qb;
        QTest::newRow("update inner join PSQL") << mBuilders.count()
                                                << QString("UPDATE table1 SET col = :0 FROM table2 WHERE ( table2.answer <> :1 AND ( table2.t1_id = table1.id ) )") << bindVals;

        qb = qbTpl;
        qb.setDatabaseType(DbType::Sqlite);
        mBuilders << qb;
        QTest::newRow("update inner join SQLite") << mBuilders.count()
                                                  << QString("UPDATE table1 SET col = :0 WHERE ( ( SELECT table2.answer FROM table2 WHERE ( ( table2.t1_id = table1.id ) ) ) <> :1 )") << bindVals;

        qb = qbTpl;
        qb.setDatabaseType(DbType::Sqlite);
        Query::Condition condition;
        condition.addValueCondition("table2.col2", Query::Equals, 666);
        condition.addValueCondition("table1.col3", Query::Equals, "text");
        qb.addCondition(condition);
        qb.addValueCondition("table1.id", Query::Equals, 10);
        mBuilders << qb;
        bindVals << 666 << "text" << 10;
        QTest::newRow("update inner join SQLite with subcondition") << mBuilders.count()
                                                                    << QString("UPDATE table1 SET col = :0 WHERE ( ( SELECT table2.answer FROM table2 WHERE "
                                                                               "( ( table2.t1_id = table1.id ) ) ) <> :1 AND "
                                                                               "( ( SELECT table2.col2 FROM table2 WHERE ( ( table2.t1_id = table1.id ) ) ) = :2 AND table1.col3 = :3 ) AND "
                                                                               "table1.id = :4 )") << bindVals;

    }
}