author | brad <brad> | 2004-04-11 12:43:55 (UTC) |
---|---|---|
committer | brad <brad> | 2004-04-11 12:43:55 (UTC) |
commit | 9716f8c5672a8596306a9b432d9fabc4361baea5 (patch) (side-by-side diff) | |
tree | 2b4f23f7e1291ff9f3ff7788068918e31ed63bef | |
parent | 40c0415fe7afeeb03de7441e2f667495e81edfa7 (diff) | |
download | opie-9716f8c5672a8596306a9b432d9fabc4361baea5.zip opie-9716f8c5672a8596306a9b432d9fabc4361baea5.tar.gz opie-9716f8c5672a8596306a9b432d9fabc4361baea5.tar.bz2 |
Fixes for sqlite regex driver. Function must be implemented as
rlike("pattern","match") instead of "where uid rlike("99")" you must
use "where rlike("99",uid). My mistake. Also fixes for pointer math for
context regex caching.
-rw-r--r-- | libopie2/opiedb/osqlitedriver.cpp | 19 | ||||
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp | 4 |
2 files changed, 14 insertions, 9 deletions
diff --git a/libopie2/opiedb/osqlitedriver.cpp b/libopie2/opiedb/osqlitedriver.cpp index ccac2f8..588fc8f 100644 --- a/libopie2/opiedb/osqlitedriver.cpp +++ b/libopie2/opiedb/osqlitedriver.cpp @@ -1,233 +1,238 @@ /* This file is part of the Opie Project =. .=l. .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU Library General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; either version 2 of the License, ._= =} : or (at your option) any later version. .%`+i> _;_. .i_,=:_. -<s. This program is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "osqlquery.h" #include "osqlitedriver.h" #include <opie2/odebug.h> #include <stdlib.h> #include <stdio.h> // fromLocal8Bit() does not work as expected. Thus it // is replaced by fromLatin1() (eilers) #define __BUGGY_LOCAL8BIT_ namespace Opie { namespace DB { namespace Internal { namespace { struct Query { OSQLError::ValueList errors; OSQLResultItem::ValueList items; OSQLiteDriver *driver; }; } OSQLiteDriver::OSQLiteDriver( QLibrary *lib ) : OSQLDriver( lib ) { m_sqlite = 0l; } OSQLiteDriver::~OSQLiteDriver() { close(); } QString OSQLiteDriver::id()const { return QString::fromLatin1("SQLite"); } void OSQLiteDriver::setUserName( const QString& ) {} void OSQLiteDriver::setPassword( const QString& ) {} void OSQLiteDriver::setUrl( const QString& url ) { m_url = url; } void OSQLiteDriver::setOptions( const QStringList& ) { } /* * Functions to patch a regex search into sqlite */ int sqliteRlikeCompare(const char *zPattern, const char *zString, sqregex *reg){ int res; - if (reg->regex_raw == NULL || (strcmp (zPattern, reg->regex_raw) != 0)){ if (reg->regex_raw != NULL) { free(reg->regex_raw); regfree(®->regex_c); } reg->regex_raw = (char *)malloc(strlen(zPattern)+1); strncpy(reg->regex_raw, zPattern, strlen(zPattern)+1); res = regcomp(®->regex_c, zPattern, REG_EXTENDED); if ( res != 0 ) { printf("Regcomp failed with code %u on string %s\n",res,zPattern); free(reg->regex_raw); reg->regex_raw=NULL; return 0; } } res = (regexec(®->regex_c, zString, 0, NULL, 0)==0); return res; } void rlikeFunc(sqlite_func *context, int arg, const char **argv){ - if( argv[0]==0 || argv[1]==0 || argv[2]==0){ + if( argv[0]==0 || argv[1]==0 ){ printf("One of arguments Null!!\n"); return; } sqlite_set_result_int(context, sqliteRlikeCompare((const char*)argv[0], - (const char*)argv[1], (sqregex*)argv[2])); + (const char*)argv[1], (sqregex *)sqlite_user_data(context) )); } /* * try to open a db specified via setUrl * and options */ bool OSQLiteDriver::open() { char *error; - qDebug("OSQLiteDriver::open: about to open"); + + qDebug("OSQLiteDriver::open: about to open"); m_sqlite = sqlite_open(m_url.local8Bit(), 0, &error ); /* failed to open */ if (m_sqlite == 0l ) { // FIXME set the last error qWarning("OSQLiteDriver::open: %s", error ); free( error ); return false; } - sqlite_create_function(m_sqlite,"rlike",3,rlikeFunc,&sqreg); + if (sqlite_create_function(m_sqlite,"rlike",2,rlikeFunc,&sqreg) != 0) + odebug << "Unable to create user defined function!" << oendl; + if (sqlite_function_type(m_sqlite,"rlike",SQLITE_NUMERIC) != 0) + odebug << "Unable to set rlike function result type!" << oendl; + sqreg.regex_raw = NULL; return true; } /* close the db * sqlite closes them without * telling failure or success */ bool OSQLiteDriver::close() { if (m_sqlite ) sqlite_close( m_sqlite ), m_sqlite=0l; if (sqreg.regex_raw != NULL){ - free(sqreg.regex_raw); + odebug << "Freeing regex on close" << oendl; + free(sqreg.regex_raw); sqreg.regex_raw=NULL; regfree(&sqreg.regex_c); } return true; } /* Query */ OSQLResult OSQLiteDriver::query( OSQLQuery* qu) { if ( !m_sqlite ) { // FIXME set error code OSQLResult result( OSQLResult::Failure ); return result; } Query query; query.driver = this; char *err; /* SQLITE_OK 0 if return code > 0 == failure */ if ( sqlite_exec(m_sqlite, qu->query(),&call_back, &query, &err) > 0 ) { - qWarning("OSQLiteDriver::query: Error while executing"); + qWarning("OSQLiteDriver::query: Error while executing %s",err); free(err ); // FixMe Errors } OSQLResult result(OSQLResult::Success, query.items, query.errors ); return result; } OSQLTable::ValueList OSQLiteDriver::tables() const { } OSQLError OSQLiteDriver::lastError() { OSQLError error; return error; }; /* handle a callback add the row to the global * OSQLResultItem */ int OSQLiteDriver::handleCallBack( int, char**, char** ) { return 0; } /* callback_handler add the values to the list*/ int OSQLiteDriver::call_back( void* voi, int argc, char** argv, char** columns) { Query* qu = (Query*)voi; //copy them over to a OSQLResultItem QMap<QString, QString> tableString; QMap<int, QString> tableInt; for (int i = 0; i < argc; i++ ) { #ifdef __BUGGY_LOCAL8BIT_ tableInt.insert( i, QString::fromLatin1( argv[i] ) ); tableString.insert( QString::fromLatin1( columns[i] ), QString::fromLatin1( argv[i] ) ); #else tableInt.insert( i, QString::fromLocal8Bit( argv[i] ) ); tableString.insert( QString::fromLocal8Bit( columns[i] ), QString::fromLocal8Bit( argv[i] ) ); #endif } OSQLResultItem item( tableString, tableInt ); qu->items.append( item ); return ((Query*)voi)->driver->handleCallBack( argc, argv, columns ); } }}} // namespace OPIE::DB::Internal diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp index bb5c99b..401a3c1 100644 --- a/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp +++ b/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp @@ -508,206 +508,206 @@ QArray<int> OPimContactAccessBackend_SQL::queryByExample ( const OPimContact &qu if ( !queryStr.isEmpty() ){ // If something is alredy stored in the query, add an "AND" // to the end of the string to prepare for the next .. if ( !searchQuery.isEmpty() ) searchQuery += " AND"; // isAnyFieldSelected = true; switch( id ){ case Qtopia::Birthday: endDate = new QDate( query.birthday() ); // Fall through ! case Qtopia::Anniversary: if ( endDate == 0l ) endDate = new QDate( query.anniversary() ); if ( settings & OPimContactAccess::DateDiff ) { searchQuery += QString( " (\"%1\" <= '%2-%3-%4\' AND \"%5\" >= '%6-%7-%8')" ) .arg( *it ) .arg( QString::number( endDate->year() ).rightJustify( 4, '0' ) ) .arg( QString::number( endDate->month() ).rightJustify( 2, '0' ) ) .arg( QString::number( endDate->day() ).rightJustify( 2, '0' ) ) .arg( *it ) .arg( QString::number( startDate.year() ).rightJustify( 4, '0' ) ) .arg( QString::number( startDate.month() ).rightJustify( 2, '0' ) ) .arg( QString::number( startDate.day() ).rightJustify( 2, '0' ) ) ; } if ( settings & OPimContactAccess::DateYear ){ if ( settings & OPimContactAccess::DateDiff ) searchQuery += " AND"; searchQuery += QString( " (\"%1\" LIKE '%2-%')" ) .arg( *it ) .arg( QString::number( endDate->year() ).rightJustify( 4, '0' ) ); } if ( settings & OPimContactAccess::DateMonth ){ if ( ( settings & OPimContactAccess::DateDiff ) || ( settings & OPimContactAccess::DateYear ) ) searchQuery += " AND"; searchQuery += QString( " (\"%1\" LIKE '%-%2-%')" ) .arg( *it ) .arg( QString::number( endDate->month() ).rightJustify( 2, '0' ) ); } if ( settings & OPimContactAccess::DateDay ){ if ( ( settings & OPimContactAccess::DateDiff ) || ( settings & OPimContactAccess::DateYear ) || ( settings & OPimContactAccess::DateMonth ) ) searchQuery += " AND"; searchQuery += QString( " (\"%1\" LIKE '%-%-%2')" ) .arg( *it ) .arg( QString::number( endDate->day() ).rightJustify( 2, '0' ) ); } break; default: // Switching between case sensitive and insensitive... // LIKE is not case sensitive, GLOB is case sensitive // Do exist a better solution to switch this ? if ( settings & OPimContactAccess::IgnoreCase ) searchQuery += "(\"" + *it + "\"" + " LIKE " + "'" + queryStr.replace(QRegExp("\\*"),"%") + "'" + ")"; else searchQuery += "(\"" + *it + "\"" + " GLOB " + "'" + queryStr + "'" + ")"; } } } // Skip trailing "AND" // if ( isAnyFieldSelected ) // qu = qu.left( qu.length() - 4 ); qu += searchQuery; qDebug( "queryByExample query: %s", qu.latin1() ); // Execute query and return the received uid's OSQLRawQuery raw( qu ); OSQLResult res = m_driver->query( &raw ); if ( res.state() != OSQLResult::Success ){ QArray<int> empty; return empty; } QArray<int> list = extractUids( res ); return list; } QArray<int> OPimContactAccessBackend_SQL::matchRegexp( const QRegExp &r ) const { -#if 1 +#if 0 QArray<int> nix(0); return nix; #else QString qu = "SELECT uid FROM addressbook WHERE ("; QString searchlist; QStringList fieldList = OPimContactFields::untrfields( false ); // QMap<QString, int> translate = OPimContactFields::untrFieldsToId(); for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){ if ( !searchlist.isEmpty() ) searchlist += " OR "; - searchlist += "\"" + *it + "\" rlike(\"" + r.pattern() + "\") "; + searchlist += " rlike(\""+ r.pattern() + "\",\"" + *it + "\") "; } qu = qu + searchlist + ")"; qDebug( "query: %s", qu.latin1() ); OSQLRawQuery raw( qu ); OSQLResult res = m_driver->query( &raw ); return extractUids( res ); #endif } const uint OPimContactAccessBackend_SQL::querySettings() { return OPimContactAccess::IgnoreCase | OPimContactAccess::WildCards | OPimContactAccess::DateDiff | OPimContactAccess::DateYear | OPimContactAccess::DateMonth | OPimContactAccess::DateDay ; } bool OPimContactAccessBackend_SQL::hasQuerySettings (uint querySettings) const { /* OPimContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay * may be added with any of the other settings. IgnoreCase should never used alone. * Wildcards, RegExp, ExactMatch should never used at the same time... */ // Step 1: Check whether the given settings are supported by this backend if ( ( querySettings & ( OPimContactAccess::IgnoreCase | OPimContactAccess::WildCards | OPimContactAccess::DateDiff | OPimContactAccess::DateYear | OPimContactAccess::DateMonth | OPimContactAccess::DateDay // | OPimContactAccess::RegExp // | OPimContactAccess::ExactMatch ) ) != querySettings ) return false; // Step 2: Check whether the given combinations are ok.. // IngoreCase alone is invalid if ( querySettings == OPimContactAccess::IgnoreCase ) return false; // WildCards, RegExp and ExactMatch should never used at the same time switch ( querySettings & ~( OPimContactAccess::IgnoreCase | OPimContactAccess::DateDiff | OPimContactAccess::DateYear | OPimContactAccess::DateMonth | OPimContactAccess::DateDay ) ){ case OPimContactAccess::RegExp: return ( true ); case OPimContactAccess::WildCards: return ( true ); case OPimContactAccess::ExactMatch: return ( true ); case 0: // one of the upper removed bits were set.. return ( true ); default: return ( false ); } } QArray<int> OPimContactAccessBackend_SQL::sorted( bool asc, int , int , int ) { QTime t; t.start(); QString query = "SELECT uid FROM addressbook "; query += "ORDER BY \"Last Name\" "; if ( !asc ) query += "DESC"; // qDebug("sorted query is: %s", query.latin1() ); OSQLRawQuery raw( query ); OSQLResult res = m_driver->query( &raw ); if ( res.state() != OSQLResult::Success ){ QArray<int> empty; return empty; } QArray<int> list = extractUids( res ); |