libopie PIM API Documentation

odatebookaccessbackend_sql.cpp

Go to the documentation of this file.
00001 /*
00002  * SQL Backend for the OPIE-Calender Database.
00003  *
00004  * Copyright (c) 2003 by Stefan Eilers (Eilers.Stefan@epost.de)
00005  *
00006  * =====================================================================
00007  *  This program is free software; you can redistribute it and/or
00008  *  modify it under the terms of the GNU Library General Public
00009  *      License as published by the Free Software Foundation; either
00010  *      version 2 of the License, or (at your option) any later version.
00011  * =====================================================================
00012  * =====================================================================
00013  * Version: $Id: odatebookaccessbackend_sql.cpp,v 1.3 2003/12/22 11:41:39 eilers Exp $
00014  * =====================================================================
00015  * History:
00016  * $Log: odatebookaccessbackend_sql.cpp,v $
00017  * Revision 1.3  2003/12/22 11:41:39  eilers
00018  * Fixing stupid bug, found by sourcode review..
00019  *
00020  * Revision 1.2  2003/12/22 10:19:26  eilers
00021  * Finishing implementation of sql-backend for datebook. But I have to
00022  * port the PIM datebook application to use it, before I could debug the
00023  * whole stuff.
00024  * Thus, PIM-Database backend is finished, but highly experimental. And some
00025  * parts are still generic. For instance, the "queryByExample()" methods are
00026  * not (or not fully) implemented. Todo: custom-entries not stored.
00027  * The big show stopper: matchRegExp() (needed by OpieSearch) needs regular
00028  * expression search in the database, which is not supported by sqlite !
00029  * Therefore we need either an extended sqlite or a workaround which would
00030  * be very slow and memory consuming..
00031  *
00032  * Revision 1.1  2003/12/08 15:18:12  eilers
00033  * Committing unfinished sql implementation before merging to libopie2 starts..
00034  *
00035  *
00036  */
00037 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 
00041 #include <qarray.h>
00042 #include <qstringlist.h>
00043 
00044 #include <qpe/global.h>
00045 
00046 #include <opie2/osqldriver.h>
00047 #include <opie2/osqlmanager.h>
00048 #include <opie2/osqlquery.h>
00049 
00050 #include "orecur.h"
00051 #include "odatebookaccessbackend_sql.h"
00052 
00053 
00054 
00055 ODateBookAccessBackend_SQL::ODateBookAccessBackend_SQL( const QString& ,
00056                                                         const QString& fileName )
00057     : ODateBookAccessBackend(), m_driver( NULL ) 
00058 {
00059     m_fileName = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.db" ) : fileName;
00060 
00061     // Get the standart sql-driver from the OSQLManager..
00062     OSQLManager man;
00063     m_driver = man.standard();
00064     m_driver->setUrl( m_fileName );
00065 
00066     initFields();
00067 
00068     load();
00069 }
00070 
00071 ODateBookAccessBackend_SQL::~ODateBookAccessBackend_SQL() {
00072     if( m_driver )
00073         delete m_driver;
00074 }
00075 
00076 void ODateBookAccessBackend_SQL::initFields()
00077 {
00078 
00079     // This map contains the translation of the fieldtype id's to 
00080     // the names of the table columns
00081     m_fieldMap.insert( OEvent::FUid, "uid" );
00082     m_fieldMap.insert( OEvent::FCategories, "Categories" );
00083     m_fieldMap.insert( OEvent::FDescription, "Description" );
00084     m_fieldMap.insert( OEvent::FLocation, "Location" );
00085     m_fieldMap.insert( OEvent::FType, "Type" );
00086     m_fieldMap.insert( OEvent::FAlarm, "Alarm" );
00087     m_fieldMap.insert( OEvent::FSound, "Sound" );
00088     m_fieldMap.insert( OEvent::FRType, "RType" );
00089     m_fieldMap.insert( OEvent::FRWeekdays, "RWeekdays" );
00090     m_fieldMap.insert( OEvent::FRPosition, "RPosition" );
00091     m_fieldMap.insert( OEvent::FRFreq, "RFreq" );
00092     m_fieldMap.insert( OEvent::FRHasEndDate, "RHasEndDate" );
00093     m_fieldMap.insert( OEvent::FREndDate, "REndDate" );
00094     m_fieldMap.insert( OEvent::FRCreated, "RCreated" );
00095     m_fieldMap.insert( OEvent::FRExceptions, "RExceptions" );
00096     m_fieldMap.insert( OEvent::FStart, "Start" );
00097     m_fieldMap.insert( OEvent::FEnd, "End" );
00098     m_fieldMap.insert( OEvent::FNote, "Note" );
00099     m_fieldMap.insert( OEvent::FTimeZone, "TimeZone" );
00100     m_fieldMap.insert( OEvent::FRecParent, "RecParent" );
00101     m_fieldMap.insert( OEvent::FRecChildren, "Recchildren" );
00102 
00103     // Create a map that maps the column name to the id
00104     QMapConstIterator<int, QString> it;
00105     for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
00106         m_reverseFieldMap.insert( it.data(), it.key() );
00107     }
00108     
00109 }
00110 
00111 bool ODateBookAccessBackend_SQL::load() 
00112 {
00113     if (!m_driver->open() )
00114         return false;
00115 
00116     // Don't expect that the database exists.
00117     // It is save here to create the table, even if it
00118     // do exist. ( Is that correct for all databases ?? )
00119     QString qu = "create table datebook( uid INTEGER PRIMARY KEY ";
00120     
00121     QMap<int, QString>::Iterator it;
00122     for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
00123         qu += QString( ",%1 VARCHAR(10)" ).arg( it.data() );
00124     }
00125     qu += " );";
00126         
00127     qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
00128 
00129     qWarning( "command: %s", qu.latin1() );
00130 
00131     OSQLRawQuery raw( qu );
00132     OSQLResult res = m_driver->query( &raw );
00133     if ( res.state() != OSQLResult::Success )
00134         return false;
00135 
00136     update();
00137 
00138     return true;
00139 }
00140 
00141 void ODateBookAccessBackend_SQL::update()
00142 {
00143 
00144     QString qu = "select uid from datebook";
00145     OSQLRawQuery raw( qu );
00146     OSQLResult res = m_driver->query( &raw );
00147     if ( res.state() != OSQLResult::Success ){
00148         // m_uids.clear();
00149         return;
00150     }
00151     
00152     m_uids = extractUids( res );
00153     
00154 }
00155 
00156 bool ODateBookAccessBackend_SQL::reload() 
00157 {
00158     return load();
00159 }
00160 
00161 bool ODateBookAccessBackend_SQL::save() 
00162 {
00163     return m_driver->close();  // Shouldn't m_driver->sync be better than close ? (eilers)
00164 }
00165 
00166 QArray<int> ODateBookAccessBackend_SQL::allRecords()const 
00167 {
00168     return m_uids;
00169 }
00170 
00171 QArray<int> ODateBookAccessBackend_SQL::queryByExample(const OEvent&, int,  const QDateTime& ) {
00172     return QArray<int>();
00173 }
00174 
00175 void ODateBookAccessBackend_SQL::clear() 
00176 {
00177     QString qu = "drop table datebook;";
00178     qu += "drop table custom_data;";
00179 
00180     OSQLRawQuery raw( qu );
00181     OSQLResult res = m_driver->query( &raw );
00182 
00183     reload();
00184 }
00185 
00186 
00187 OEvent ODateBookAccessBackend_SQL::find( int uid ) const{
00188     QString qu = "select *";
00189     qu += "from datebook where uid = " + QString::number(uid);
00190 
00191     OSQLRawQuery raw( qu );
00192     OSQLResult res = m_driver->query( &raw );
00193 
00194     OSQLResultItem resItem = res.first();
00195 
00196     // Create Map for date event and insert UID
00197     QMap<int,QString> dateEventMap;
00198     dateEventMap.insert( OEvent::FUid, QString::number( uid ) );
00199 
00200     // Now insert the data out of the columns into the map.
00201     QMapConstIterator<int, QString> it;
00202     for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
00203         dateEventMap.insert( m_reverseFieldMap[*it], resItem.data( *it ) );
00204     }
00205 
00206     // Last step: Put map into date event and return it
00207     OEvent retDate( dateEventMap );
00208 
00209     return retDate;
00210 }
00211 
00212 // FIXME: Speed up update of uid's..
00213 bool ODateBookAccessBackend_SQL::add( const OEvent& ev ) 
00214 {
00215     QMap<int,QString> eventMap = ev.toMap();
00216 
00217     QString qu = "insert into datebook VALUES( " + QString::number( ev.uid() );
00218     QMap<int, QString>::Iterator it;
00219     for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
00220         if ( !eventMap[it.key()].isEmpty() )
00221             qu += QString( ",\"%1\"" ).arg( eventMap[it.key()] );
00222         else
00223             qu += QString( ",\"\"" );
00224     }
00225     qu += " );";
00226 
00227     // Add custom entries
00228     int id = 0;
00229     QMap<QString, QString> customMap = ev.toExtraMap();
00230     for( QMap<QString, QString>::Iterator it = customMap.begin(); 
00231          it != customMap.end(); ++it ){
00232         qu  += "insert into custom_data VALUES(" 
00233             +  QString::number( ev.uid() )
00234             + ","
00235             +  QString::number( id++ ) 
00236             + ",'" 
00237             + it.key() //.latin1()
00238             + "',"
00239             + "0" // Priority for future enhancements
00240             + ",'" 
00241             + it.data() //.latin1()
00242             + "');";
00243     }       
00244     qWarning("add %s", qu.latin1() );
00245 
00246     OSQLRawQuery raw( qu );
00247     OSQLResult res = m_driver->query( &raw );
00248     if ( res.state() != OSQLResult::Success ){
00249         return false;
00250     }
00251 
00252     // Update list of uid's 
00253     update();
00254     
00255     return true;
00256 }
00257 
00258 // FIXME: Speed up update of uid's..
00259 bool ODateBookAccessBackend_SQL::remove( int uid ) 
00260 {
00261     QString qu = "DELETE from datebook where uid = " 
00262         + QString::number( uid ) + ";";
00263     qu += "DELETE from custom_data where uid = " 
00264         + QString::number( uid ) + ";";
00265     
00266     OSQLRawQuery raw( qu );
00267     OSQLResult res = m_driver->query( &raw );
00268     if ( res.state() != OSQLResult::Success ){
00269         return false;
00270     }
00271 
00272     // Update list of uid's
00273     update();
00274 
00275     return true;
00276 }
00277 
00278 bool ODateBookAccessBackend_SQL::replace( const OEvent& ev ) 
00279 {
00280     remove( ev.uid() );
00281     return add( ev );
00282 }
00283 
00284 QArray<int> ODateBookAccessBackend_SQL::rawEvents()const 
00285 {
00286     return allRecords();
00287 }
00288 
00289 QArray<int> ODateBookAccessBackend_SQL::rawRepeats()const 
00290 {
00291     QString qu = "select uid from datebook where RType!=\"\" AND RType!=\"NoRepeat\"";
00292     OSQLRawQuery raw( qu );
00293     OSQLResult res = m_driver->query( &raw );
00294     if ( res.state() != OSQLResult::Success ){
00295         QArray<int> nix;
00296         return nix;
00297     }
00298     
00299     return extractUids( res );
00300 }
00301 
00302 QArray<int> ODateBookAccessBackend_SQL::nonRepeats()const 
00303 {
00304     QString qu = "select uid from datebook where RType=\"\" or RType=\"NoRepeat\"";
00305     OSQLRawQuery raw( qu );
00306     OSQLResult res = m_driver->query( &raw );
00307     if ( res.state() != OSQLResult::Success ){
00308         QArray<int> nix;
00309         return nix;
00310     }
00311     
00312     return extractUids( res );
00313 }
00314 
00315 OEvent::ValueList ODateBookAccessBackend_SQL::directNonRepeats() 
00316 {
00317     QArray<int> nonRepUids = nonRepeats();
00318     OEvent::ValueList list;
00319 
00320     for (uint i = 0; i < nonRepUids.count(); ++i ){
00321         list.append( find( nonRepUids[i] ) );
00322     }
00323 
00324     return list;
00325 
00326 }
00327 OEvent::ValueList ODateBookAccessBackend_SQL::directRawRepeats() 
00328 {
00329     QArray<int> rawRepUids = rawRepeats();
00330     OEvent::ValueList list;
00331 
00332     for (uint i = 0; i < rawRepUids.count(); ++i ){
00333         list.append( find( rawRepUids[i] ) );
00334     }
00335 
00336     return list;
00337 }
00338 
00339 
00340 QArray<int> ODateBookAccessBackend_SQL::matchRegexp(  const QRegExp &r ) const
00341 {
00342     QArray<int> null;
00343     return null;
00344 }
00345 
00346 /* ===== Private Functions ========================================== */
00347 
00348 QArray<int> ODateBookAccessBackend_SQL::extractUids( OSQLResult& res ) const
00349 {
00350     qWarning("extractUids");
00351     QTime t;
00352     t.start();
00353     OSQLResultItem::ValueList list = res.results();
00354     OSQLResultItem::ValueList::Iterator it;
00355     QArray<int> ints(list.count() );
00356     qWarning(" count = %d", list.count() );
00357 
00358     int i = 0;
00359     for (it = list.begin(); it != list.end(); ++it ) {
00360         ints[i] =  (*it).data("uid").toInt();
00361         i++;
00362     }
00363     qWarning("extractUids ready: count2 = %d needs %d ms", i, t.elapsed() );
00364 
00365     return ints;
00366 
00367 }
KDE Logo
This file is part of the documentation for OPIE Version 1.1.
Documentation copyright © 1997-2003 the KDE developers. 2003 OPIE developers
Generated on Tue Feb 10 20:25:20 2004 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2001