// (c) 2004 Mark Kretschmann // (c) 2004 Christian Muehlhaeuser // (c) 2004 Sami Nieminen // (c) 2005 Ian Monroe // See COPYING file for licensing information. #ifndef KLAMAV_COLLECTIONDB_H #define KLAMAV_COLLECTIONDB_H #include #include //stack allocated #include #include //baseclass #include //baseclass #include //stack allocated #include //stack allocated class DbConnection; class DbConnectionPool; class DbConfig {}; class SqliteConfig : public DbConfig { public: SqliteConfig( const QString& /* dbfile */ ); const QString dbFile() const { return m_dbfile; } private: QString m_dbfile; }; class DbConnection { public: enum DbConnectionType { sqlite = 0, mysql = 1, postgresql = 2 }; DbConnection( DbConfig* /* config */ ); virtual ~DbConnection() = 0; virtual QStringList query( const QString& /* statement */ ) = 0; virtual int insert( const QString& /* statement */, const QString& /* table */ ) = 0; const bool isInitialized() const { return m_initialized; } virtual bool isConnected() const = 0; virtual const QString lastError() const { return "None"; } protected: bool m_initialized; DbConfig *m_config; }; typedef struct sqlite3 sqlite3; typedef struct sqlite3_context sqlite3_context; typedef struct Mem sqlite3_value; class SqliteConnection : public DbConnection { public: SqliteConnection( SqliteConfig* /* config */ ); ~SqliteConnection(); QStringList query( const QString& /* statement */ ); int insert( const QString& /* statement */, const QString& /* table */ ); bool isConnected()const { return true; } private: static void sqlite_rand(sqlite3_context *context, int /*argc*/, sqlite3_value ** /*argv*/); static void sqlite_power(sqlite3_context *context, int argc, sqlite3_value **argv); sqlite3* m_db; }; class DbConnectionPool : QPtrQueue { public: DbConnectionPool( bool temporary ); ~DbConnectionPool(); const DbConnection::DbConnectionType getDbConnectionType() const { return m_dbConnType; } const DbConfig *getDbConfig() const { return m_dbConfig; } void createDbConnections(); DbConnection *getDbConnection(); void putDbConnection( const DbConnection* /* conn */ ); QString escapeString( QString string ) { return string.replace( '\'', "''" ); } private: static const int POOL_SIZE = 5; bool m_isTemporary; QSemaphore m_semaphore; DbConnection::DbConnectionType m_dbConnType; DbConfig *m_dbConfig; }; class CollectionDB : public QObject { Q_OBJECT signals: public: CollectionDB( bool temporary = false ); ~CollectionDB(); static CollectionDB *instance(); const QString escapeString( const QString &string ) { return m_dbConnPool->escapeString(string); } const QString boolT() { if (m_dbConnPool->getDbConnectionType() == DbConnection::postgresql) return "'t'"; else return "1"; } const QString boolF() { if (m_dbConnPool->getDbConnectionType() == DbConnection::postgresql) return "'f'"; else return "0"; } const QString textColumnType() { if ( m_dbConnPool->getDbConnectionType() == DbConnection::postgresql ) return "TEXT"; else return "VARCHAR(255)"; } const QString textColumnType(int length){ if ( m_dbConnPool->getDbConnectionType() == DbConnection::postgresql ) return "TEXT"; else return QString("VARCHAR(%1)").arg(length); } // We might consider using LONGTEXT type, as some lyrics could be VERY long..??? const QString longTextColumnType() { if ( m_dbConnPool->getDbConnectionType() == DbConnection::postgresql ) return "TEXT"; else return "TEXT"; } const QString randomFunc() { if ( m_dbConnPool->getDbConnectionType() == DbConnection::postgresql ) return "random()"; else return "RAND()"; } int getType() { return m_dbConnPool->getDbConnectionType(); } /** * This method returns a static DbConnection for components that want to use * the same connection for the whole time. Should not be used anywhere else * but in CollectionReader. * * @return static DbConnection */ DbConnection *getStaticDbConnection(); /** * Returns the DbConnection back to connection pool. * * @param conn DbConnection to be returned */ void returnStaticDbConnection( DbConnection *conn ); //sql helper methods QStringList query( const QString& statement, DbConnection *conn = NULL ); int insert( const QString& statement, const QString& table, DbConnection *conn = NULL ); //table management methods bool isEmpty(); bool isValid(const QString &column, const QString &table); void createTables( DbConnection *conn = NULL ); void createActivityTable( DbConnection *conn = NULL ); void createMetaDBTable( DbConnection *conn = NULL ); void loadMetaDBTable( DbConnection *conn = NULL ); void dropTables( DbConnection *conn = NULL ); void clearTables( DbConnection *conn = NULL ); void moveTempTables( DbConnection *conn ); QString typeCount( const QString &type_id ); QStringList messagesForType( const QString &type_id, const bool isValue ); QStringList allActivity( ); QStringList allActivityOfType(const QString &type, const QString &days ); void insertEvent(const QString &type, const QString &event,const QString &file = NULL, DbConnection *conn = NULL ); void expireActivity(const QString &days ); void insertMetaDBEntry(const QString &date, const QString &submission, const QString &creator,const QString &virus,const QString &alias, const QString &sender,DbConnection *conn = NULL); QString latestMetaDBDate( ); protected: QCString md5sum( const QString& artist, const QString& album, const QString& file = QString::null ); /** Manages regular folder monitoring scan */ public slots: private slots: private: //bump DATABASE_VERSION whenever changes to the table structure are made. will remove old db file. static const int DATABASE_VERSION = 20; static const int DATABASE_STATS_VERSION = 3; static const int MONITOR_INTERVAL = 60; //sec static const bool DEBUGSQL = false; void initialize(); void destroy(); //general management methods uint IDFromValue( QString name, QString value, bool autocreate = true, const bool temporary = false, const bool updateSpelling = false, DbConnection *conn = NULL ); QString valueFromID( QString table, uint id ); //member variables DbConnectionPool *m_dbConnPool; bool m_isTemporary; bool m_monitor; }; #endif /* KLAMAV_COLLECTIONDB_H */