Example #1
0
/*
 * this method saves the attribute together with the host string that
 * defines the type of object that this attribute is associated to (like
 * position or document) and the hosts database id.
 */
void AttributeMap::save( dbID id )
{
    checkHost();

    QSqlQuery attribQuery;
    attribQuery.prepare( "SELECT id, valueIsList FROM attributes WHERE hostObject=:host AND hostId=:hostId AND name=:name" );

    attribQuery.bindValue( ":host", mHost );
    attribQuery.bindValue( ":hostId", id.toString() );

    Iterator it;
    for ( it = begin(); it != end(); ++it ) {
        Attribute att = it.value();
        kDebug() << ">> oo-  saving attribute with name " << it.key() << " for " << id.toString() << " att-name: " << att.name();

        attribQuery.bindValue( ":name", att.name() );
        attribQuery.exec();

        QString attribId;

        if ( attribQuery.next() ) {
            // the attrib exists. Check the values

            attribId = attribQuery.value(0).toString();  // the id
            if ( att.value().isNull() || att.mDelete ) {
                // the value is empty. the existing entry needs to be dropped
                dbDeleteAttribute( attribId );
                return;
            }
        } else {
            // the attrib does not yet exist. Create if att value is not null.
            if ( att.value().isNull() ) {
                kDebug() << "oo- skip writing of attribute, value is empty";
            } else {
                kDebug() << "oo- writing of attribute name " << att.name();
                QSqlQuery insQuery;
                insQuery.prepare( "INSERT INTO attributes (hostObject, hostId, name, valueIsList, relationTable, "
                                  "relationIDColumn, relationStringColumn) "
                                  "VALUES (:host, :hostId, :name, :valueIsList, :relTable, :relIDCol, :relStringCol )" );
                insQuery.bindValue( ":host", mHost );
                insQuery.bindValue( ":hostId", id.toString() );
                insQuery.bindValue( ":name", att.name() );
                insQuery.bindValue( ":valueIsList", att.listValue() );

                // Write the relation table info. These remain empty for non related attributes.
                insQuery.bindValue( ":relTable", att.mTable );
                insQuery.bindValue( ":relIDCol", att.mIdCol );
                insQuery.bindValue( ":relStringCol", att.mStringCol );

                insQuery.exec();
                dbID attId = KraftDB::self()->getLastInsertID();
                attribId = attId.toString();
            }
        }

        // store the id to be able to drop not longer existent values
        kDebug() << "adding attribute id " << attribId << " for attribute " << att.name();

        // now there is a valid entry in the attribute table. Check the values.
        QSqlQuery valueQuery( "SELECT id, value FROM attributeValues WHERE attributeId=" + attribId );

        typedef QMap<QString, QString> ValueMap;
        ValueMap valueMap;

        while ( valueQuery.next() ) {
            QString idStr = valueQuery.value( 0 ).toString(); // id
            QString valStr = valueQuery.value( 1 ).toString(); // value

            valueMap[valStr] = idStr;
        }

        // create a stringlist with the current values of the attribute
        if ( att.listValue() ) {
            QStringList newValues;
            newValues = att.mValue.toStringList();
            kDebug() << "new values are: " << newValues.join( ", " );

            if ( newValues.empty() ) {
                // delete the entire attribute.
                dbDeleteValue( attribId ); // deletes all values
                dbDeleteAttribute( attribId );
                valueMap.clear();
            } else {
                // we really have new values

                QSqlQuery insValue;
                insValue.prepare( "INSERT INTO attributeValues (attributeId, value) VALUES (:attribId, :val)" );
                insValue.bindValue( ":attribId", attribId );

                // loop over all existing new values of the attribute.
                for ( QStringList::Iterator valIt = newValues.begin(); valIt != newValues.end(); ++valIt ) {
                    QString curValue = *valIt;

                    if ( valueMap.contains( curValue ) ) {
                        // the valueMap is already saved. remove it from the valueMap string
                        kDebug() << "Value " << curValue << " is already present with id " << valueMap[curValue];
                        valueMap.remove( curValue );
                    } else {
                        // the value is not yet there, insert it.
                        insValue.bindValue( ":val", curValue );
                        insValue.exec();
                    }
                }
            }
        } else {
            // only a single entry for the attribte, update if needed.
            QString newValue = att.mValue.toString();  // access the attribute object directly to get the numeric
            kDebug() << "NEW value String: " << newValue;
            // value in case the attribute is bound to a relation table
            if ( newValue.isEmpty() ) {
                // delete the entire attribute
                dbDeleteValue( attribId ); // deletes all values
                dbDeleteAttribute( attribId );
                valueMap.clear();
            } else {
                if ( valueMap.empty() ) {
                    // there is no entry yet that could be updated.
                    QSqlQuery insertQuery;
                    insertQuery.prepare( "INSERT INTO attributeValues (attributeId, value ) VALUES (:id, :val)" );
                    insertQuery.bindValue( ":id", attribId );
                    insertQuery.bindValue( ":val", newValue );

                    insertQuery.exec();
                    kDebug() << "insert new attrib value for non list: " << newValue;

                } else {
                    QString oldValue = valueMap.begin().key();
                    QString id = valueMap.begin().value();

                    if ( newValue != oldValue ) {
                        kDebug() << "Updating " << id << " from " << oldValue << " to " << newValue;
                        QSqlQuery updateQuery;
                        updateQuery.prepare( "UPDATE attributeValues SET value=:val WHERE id=:id" );
                        updateQuery.bindValue( ":val", newValue );
                        updateQuery.bindValue( ":id",  id );
                        kDebug() << "do the update!";
                        updateQuery.exec();
                    }
                    valueMap.remove( oldValue );
                }
            }
        }

        // remove all still existing entries in the valueMap because they point to values which are
        // in the db but were deleted from the attribute
        if ( ! valueMap.isEmpty() ) {
            ValueMap::Iterator mapIt;
            for ( mapIt = valueMap.begin(); mapIt != valueMap.end(); ++mapIt ) {
                QString valId = mapIt.value();
                dbDeleteValue( attribId, valId );
            }
        }
    }
}