diff --git a/src/server/storage/entities-source.xsl b/src/server/storage/entities-source.xsl index 3c74eed5e..edf077ddc 100644 --- a/src/server/storage/entities-source.xsl +++ b/src/server/storage/entities-source.xsl @@ -1,769 +1,755 @@ Table // private class class ::Private : public QSharedData { public: Private() : QSharedData() , ( 0 ) , () , () // on non-wince, QDateTime is one int , () , ( 0 ) , ( false ) , ( 0 ) , _changed( false ) {} qint64 ; QString ; QByteArray ; // on non-wince, QDateTime is one int QDateTime ; int ; bool : 1; Tristate ; ; bool _changed : 1; static void addToCache( const & entry ); // cache static QAtomicInt cacheEnabled; static QMutex cacheMutex; static QHash<qint64, > idCache; static QHash<, > nameCache; }; // static members QAtomicInt ::Private::cacheEnabled(0); QMutex ::Private::cacheMutex; QHash<qint64, > ::Private::idCache; QHash<, > ::Private::nameCache; void ::Private::addToCache( const & entry ) { Q_ASSERT( cacheEnabled ); Q_UNUSED( entry ); QMutexLocker lock(&cacheMutex); idCache.insert( entry.id(), entry ); nameCache.insert( entry.ns() + QLatin1Char(':') + entry.name(), entry ); nameCache.insert( entry.name(), entry ); } // constructor ::() : Entity(), d( new Private ) { } ::( , ) : Entity(), d( new Private ) { d-> = ; d->_changed = true; } ::( , ) : Entity( id ), d( new Private ) { d-> = ; d->_changed = true; } ::( const & other ) : Entity( other ), d( other.d ) { } // destructor ::~() {} // assignment operator & ::operator=( const & other ) { if ( this != &other ) { d = other.d; setId( other.id() ); } return *this; } // comparisson operator bool ::operator==( const & other ) const { return id() == other.id(); } // accessor methods ::() const { return d->; } void :: { d-> = ; d->_changed = true; } // SQL table information QString ::tableName() { static const QString tableName = QStringLiteral( "" ); return tableName; } QStringList ::columnNames() { static const QStringList columns = QStringList() << Column() ; return columns; } QStringList ::fullColumnNames() { static const QStringList columns = QStringList() << FullColumnName() ; return columns; } QString ::Column() { static const QString column = QStringLiteral( "" ); return column; } QString ::FullColumnName() { static const QString column = QStringLiteral( "." ); return column; } // count records int ::count( const QString &column, const QVariant &value ) { return Entity::count<>( column, value ); } // check existence bool ::exists( qint64 id ) { if ( Private::cacheEnabled ) { QMutexLocker lock(&Private::cacheMutex); if ( Private::idCache.contains( id ) ) { return true; } } return count( idColumn(), id ) > 0; } bool ::exists( const &name ) { if ( Private::cacheEnabled ) { QMutexLocker lock(&Private::cacheMutex); if ( Private::nameCache.contains( name ) ) { return true; } } return count( nameColumn(), name ) > 0; } // result extraction QVector< > ::extractResult( QSqlQuery & query ) { QVector<> rv; if (query.driver()->hasFeature(QSqlDriver::QuerySize)) { rv.reserve(query.size()); } while ( query.next() ) { rv.append( ( (query.isNull()) ? () : Utils::variantToString( query.value( ) ) static_cast<>(query.value( ).value<int>()) query.value( ).value<>() , ) ); } return rv; } // data retrieval ::retrieveById( qint64 id ) { id idCache } ::retrieveByName( const &name ) { name nameCache } ::retrieveByNameOrCreate( const &name) { static QMutex lock; + QMutexLocker locker(&lock); auto rv = retrieveByName(name); if (rv.isValid()) { return rv; } - if (lock.tryLock()) { - rv.setName(name); - if (!rv.insert()) { - lock.unlock(); - return (); - } - - if (Private::cacheEnabled) { - Private::addToCache(rv); - } - lock.unlock(); - return rv; + rv.setName(name); + if (!rv.insert()) { + return (); } - lock.lock(); - lock.unlock(); - return retrieveByName(name); + if (Private::cacheEnabled) { + Private::addToCache(rv); + } + return rv; } PartType PartType::retrieveByFQName( const QString & ns, const QString & name ) { const QString fqname = ns + QLatin1Char(':') + name; ns name fqname nameCache } PartType PartType::retrieveByFQNameOrCreate( const QString & ns, const QString & name ) { static QMutex lock; + QMutexLocker locker(&lock); PartType rv = retrieveByFQName(ns, name); if (rv.isValid()) { return rv; } - if (lock.tryLock()) { - rv.setNs(ns); - rv.setName(name); - if (!rv.insert()) { - lock.unlock(); - return PartType(); - } - - if (Private::cacheEnabled) { - Private::addToCache(rv); - } - lock.unlock(); - return rv; + rv.setNs(ns); + rv.setName(name); + if (!rv.insert()) { + return PartType(); } - lock.lock(); - lock.unlock(); - return retrieveByFQName(ns, name); + if (Private::cacheEnabled) { + Private::addToCache(rv); + } + return rv; } QVector<> ::retrieveAll() { QSqlDatabase db = DataStore::self()->database(); if ( !db.isOpen() ) return QVector<>(); QueryBuilder qb( tableName(), QueryBuilder::Select ); qb.addColumns( columnNames() ); if ( !qb.exec() ) { qCWarning(AKONADISERVER_LOG) << "Error during selection of all records from table" << tableName() << qb.query().lastError().text() << qb.query().lastQuery(); return QVector<>(); } return extractResult( qb.query() ); } QVector<> ::retrieveFiltered( const QString &key, const QVariant &value ) { QSqlDatabase db = DataStore::self()->database(); if ( !db.isOpen() ) return QVector<>(); SelectQueryBuilder<> qb; if ( value.isNull() ) qb.addValueCondition( key, Query::Is, QVariant() ); else qb.addValueCondition( key, Query::Equals, value ); if ( !qb.exec() ) { qCWarning(AKONADISERVER_LOG) << "Error during selection of records from table" << tableName() << "filtered by" << key << "=" << value << qb.query().lastError().text(); return QVector<>(); } return qb.result(); } // data retrieval for referenced tables ::() const { return ::retrieveById( () ); } void :: set ( const &value ) { d-> = value.id(); d->_changed = true; } // data retrieval for inverse referenced tables QVector<> ::() const { return ::retrieveFiltered( ::Column(), id() ); } Relation // data retrieval for n:m relations QVector<> ::s() const { QSqlDatabase db = DataStore::self()->database(); if ( !db.isOpen() ) return QVector<>(); QueryBuilder qb( ::tableName(), QueryBuilder::Select ); static const QStringList columns = QStringList() << ::FullColumnName() ; qb.addColumns(columns); qb.addJoin( QueryBuilder::InnerJoin, ::tableName(), ::rightFullColumnName(), ::FullColumnName() ); qb.addValueCondition( ::leftFullColumnName(), Query::Equals, id() ); if ( !qb.exec() ) { qCWarning(AKONADISERVER_LOG) << "Error during selection of records from table Relation" << qb.query().lastError().text(); return QVector<>(); } return ::extractResult( qb.query() ); } // manipulate n:m relations bool ::relatesTo( const & value ) const { return Entity::relatesTo<>( id(), value.id() ); } bool ::relatesTo( qint64 leftId, qint64 rightId ) { return Entity::relatesTo<>( leftId, rightId ); } bool ::add( const & value ) const { return Entity::addToRelation<>( id(), value.id() ); } bool ::add( qint64 leftId, qint64 rightId ) { return Entity::addToRelation<>( leftId, rightId ); } bool ::remove( const & value ) const { return Entity::removeFromRelation<>( id(), value.id() ); } bool ::remove( qint64 leftId, qint64 rightId ) { return Entity::removeFromRelation<>( leftId, rightId ); } bool ::clears() const { return Entity::clearRelation<>( id() ); } bool ::clears( qint64 id ) { return Entity::clearRelation<>( id ); } #ifndef QT_NO_DEBUG_STREAM // debug stream operator QDebug & operator<<( QDebug& d, const & entity ) { d << "[: " << " = " << static_cast<int>(entity.()) entity.() << ", " << "]"; return d; } #endif // inserting new data bool ::insert( qint64* insertId ) { QSqlDatabase db = DataStore::self()->database(); if ( !db.isOpen() ) return false; QueryBuilder qb( tableName(), QueryBuilder::Insert ); qb.setIdentificationColumn(QLatin1String("")); if ( d->_changed && d-> > 0 ) qb.setColumnValue( Column(), this->() ); if ( d->_changed ) qb.setColumnValue( Column(), static_cast<int>(this->()) ); qb.setColumnValue( Column(), this->() ); if ( !qb.exec() ) { qCWarning(AKONADISERVER_LOG) << "Error during insertion into table" << tableName() << qb.query().lastError().text(); return false; } setId( qb.insertId() ); if ( insertId ) *insertId = id(); return true; } bool ::hasPendingChanges() const { return false || d->_changed ; } // update existing data bool ::update() { invalidateCache(); QSqlDatabase db = DataStore::self()->database(); if ( !db.isOpen() ) return false; QueryBuilder qb( tableName(), QueryBuilder::Update ); if ( d->_changed ) { if ( d-> <= 0 ) qb.setColumnValue( Column(), QVariant() ); else qb.setColumnValue( Column(), static_cast<int>(this->()) ); qb.setColumnValue( Column(), this->() ); } qb.addValueCondition( idColumn(), Query::Equals, id() ); if ( !qb.exec() ) { qCWarning(AKONADISERVER_LOG) << "Error during updating record with id" << id() << " in table" << tableName() << qb.query().lastError().text(); return false; } return true; } // delete records bool ::remove( const QString &column, const QVariant &value ) { invalidateCompleteCache(); return Entity::remove<>( column, value ); } bool ::remove() { invalidateCache(); return Entity::remove<>( idColumn(), id() ); } bool ::remove( qint64 id ) { return remove( idColumn(), id ); } // cache stuff void ::invalidateCache() const { if ( Private::cacheEnabled ) { QMutexLocker lock(&Private::cacheMutex); Private::idCache.remove( id() ); Private::nameCache.remove( ns() + QLatin1Char(':') + name() ); Private::nameCache.remove( name() ); } } void ::invalidateCompleteCache() { if ( Private::cacheEnabled ) { QMutexLocker lock(&Private::cacheMutex); Private::idCache.clear(); Private::nameCache.clear(); } } void ::enableCache( bool enable ) { Private::cacheEnabled = enable; } Relation Relation // SQL table information QString ::tableName() { static const QString table = QStringLiteral( "" ); return table; } QString ::leftColumn() { static const QString column = QStringLiteral( "_" ); return column; } QString ::leftFullColumnName() { static const QString column = QStringLiteral( "._" ); return column; } QString ::rightColumn() { static const QString column = QStringLiteral( "_" ); return column; } QString ::rightFullColumnName() { static const QString column = QStringLiteral( "._" ); return column; }