qtmobility/plugins/contacts/symbian/src/filtering/cntsymbianfiltersqlhelper.cpp
changeset 4 90517678cc4f
parent 1 2b40d63a9c3d
child 5 453da2cfceef
equal deleted inserted replaced
1:2b40d63a9c3d 4:90517678cc4f
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtCore module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 //system includes
       
    42 #include <e32base.h>
       
    43 #include <s32mem.h>
       
    44 #include <centralrepository.h>
       
    45 
       
    46 #include <QDebug>
       
    47 
       
    48 //user includes
       
    49 #include "cntsymbianfiltersqlhelper.h"
       
    50 #include "qcontactdetailfilter.h"
       
    51 #include "cnttransformcontact.h"
       
    52 #include "cntdisplaylabel.h"
       
    53 #include "cntdisplaylabelsqlfilter.h"
       
    54 #include "cntsqlsearch.h"
       
    55 
       
    56 // Telephony Configuration API
       
    57 // Keys under this category are used in defining telephony configuration.
       
    58 const TUid KCRUidTelConfiguration = {0x102828B8};
       
    59 // Amount of digits to be used in contact matching.
       
    60 // This allows a customer to variate the amount of digits to be matched.
       
    61 const TUint32 KTelMatchDigits                               = 0x00000001;
       
    62 // Default match length
       
    63 const TInt KDefaultMatchLength(7);
       
    64 //Class documentation go here:
       
    65 /*!
       
    66     \class CntSymbianFilterSqlHelper
       
    67     \brief Helper class for converting filter to sql queries
       
    68 */
       
    69 
       
    70  Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::SingleQuote,"'")  ;
       
    71  Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::PercentSign,"%") ;
       
    72  Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::Space," ") ;
       
    73  Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::EqualTo,"=") ;
       
    74  Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::SqlLike," LIKE ") ;
       
    75  Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::SqlNotNull," NOT NULL ") ;
       
    76  Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::SqlWhere," WHERE ") ;
       
    77  Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::SqlOr," OR ") ;
       
    78  Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::contactsTable," contact ") ;
       
    79  Q_DEFINE_LATIN1_LITERAL(CntSymbianFilterSqlHelper::commAddrTable," comm_addr ") ;
       
    80  
       
    81 
       
    82 /*!
       
    83  * The constructor
       
    84  */
       
    85 CntSymbianFilterSqlHelper::CntSymbianFilterSqlHelper(CContactDatabase& contactDatabase)
       
    86                                                : m_contactDatabase(contactDatabase),
       
    87                                                  isPhoneNumberSearchforDetailFilter(false)
       
    88 {
       
    89    m_srvConnection = new CntSymbianSrvConnection();
       
    90    m_sqlSearch = new CntSqlSearch();
       
    91 
       
    92    contactsTableIdColumNameMapping.insert(KUidContactFieldGivenName.iUid,"first_name" );
       
    93    contactsTableIdColumNameMapping.insert(KUidContactFieldGivenNamePronunciation.iUid,"firstname_prn" );
       
    94    contactsTableIdColumNameMapping.insert(KUidContactFieldFamilyName.iUid,"last_name" );
       
    95    contactsTableIdColumNameMapping.insert(KUidContactFieldFamilyNamePronunciation.iUid,"lastname_prn" );
       
    96    contactsTableIdColumNameMapping.insert(KUidContactFieldCompanyName.iUid,"company_name" );
       
    97    contactsTableIdColumNameMapping.insert(KUidContactFieldCompanyNamePronunciation.iUid,"companyname_prn" );
       
    98 
       
    99    //commAddrTableIdColumNameMapping.insert(KUidContactFieldIMPP.iUid,ESipAddress );
       
   100    commAddrTableIdColumNameMapping.insert(KUidContactFieldSIPID.iUid,ESipAddress );
       
   101    commAddrTableIdColumNameMapping.insert(KUidContactFieldEMail.iUid,EEmailAddress );
       
   102 
       
   103 }
       
   104 
       
   105 /*!
       
   106  * Destructor
       
   107  */
       
   108 CntSymbianFilterSqlHelper::~CntSymbianFilterSqlHelper()
       
   109 
       
   110 {
       
   111     delete m_srvConnection;
       
   112     delete m_sqlSearch;
       
   113     contactsTableIdColumNameMapping.clear();
       
   114     commAddrTableIdColumNameMapping.clear();
       
   115 }
       
   116 
       
   117 /*!
       
   118  * Fetch search results from the database.
       
   119  *
       
   120  * \a filter The simple/complex QContactFilter passed .
       
   121  * \a error On return, contains the possible error.
       
   122  * \return the list of matched contact ids
       
   123  */
       
   124 QList<QContactLocalId> CntSymbianFilterSqlHelper::searchContacts(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders,
       
   125                                                                   QContactManager::Error& error)
       
   126 {
       
   127     isPhoneNumberSearchforDetailFilter = false;
       
   128     QList<QContactLocalId> idList;
       
   129     bool isPredSearch;
       
   130     idList =  HandlePredictiveSearchFilter(filter,isPredSearch, error);
       
   131     if(isPredSearch)
       
   132             return idList;
       
   133    if(filterSupportLevel(filter)){
       
   134         
       
   135         // Create sql query from the filters
       
   136         QString sqlQuery;
       
   137         createSqlQuery(filter, sqlQuery, error);
       
   138 
       
   139         if( error != QContactManager::NoError) {
       
   140             return QList<QContactLocalId>();
       
   141         }
       
   142         // Query the database
       
   143         // If isPhoneNumberSearchforDetailFilter flag is set, we use the existing cntmodel
       
   144         // else call searchContacts
       
   145         if(isPhoneNumberSearchforDetailFilter)
       
   146         {
       
   147             // cast the filter into detail filte
       
   148             const QContactDetailFilter detailFilter(filter);
       
   149             idList = HandlePhonenumberDetailFilter(detailFilter);
       
   150         }
       
   151         else
       
   152         {
       
   153             //append the sort order to the query
       
   154             appendSortOrderQuery(sqlQuery, sortOrders);
       
   155             
       
   156             //fetch the contacts
       
   157             idList =  m_srvConnection->searchContacts(sqlQuery, error);
       
   158         }
       
   159 
       
   160     }
       
   161     else
       
   162         {
       
   163         error = QContactManager::NotSupportedError;
       
   164         }
       
   165     return idList;
       
   166     
       
   167         
       
   168 }
       
   169 
       
   170 QList<QContactLocalId>  CntSymbianFilterSqlHelper::HandlePredictiveSearchFilter(const QContactFilter& filter, bool &isPredSearch,
       
   171         QContactManager::Error& error)
       
   172     {
       
   173     isPredSearch = false;
       
   174     QString sqlQuery;
       
   175     if(filter.type() == QContactFilter::ContactDetailFilter){
       
   176        const QContactDetailFilter detailFilter(filter);
       
   177        if(  detailFilter.matchFlags() == QContactFilter::MatchKeypadCollation ){
       
   178           //convert string to numeric format
       
   179             QString pattern = detailFilter.value().toString();
       
   180             sqlQuery = m_sqlSearch->CreatePredictiveSearch(pattern);
       
   181             isPredSearch = true;
       
   182         
       
   183             return  m_srvConnection->searchContacts(sqlQuery, error);  
       
   184            }
       
   185        else
       
   186            {
       
   187            return QList<QContactLocalId>();
       
   188            }
       
   189         }
       
   190     else
       
   191         {
       
   192         return QList<QContactLocalId>();
       
   193         }
       
   194     }
       
   195 
       
   196 /*!
       
   197  * Append the sort order to the sql query
       
   198  *
       
   199  * \a sqlQuery to add the sort order to
       
   200  * \a sortOrders to be added
       
   201  */
       
   202 void CntSymbianFilterSqlHelper::appendSortOrderQuery(QString& sqlQuery, const QList<QContactSortOrder>& sortOrders)
       
   203 {
       
   204     QString column;
       
   205     CntDisplayLabel displayLabel;
       
   206     
       
   207     bool first(true);
       
   208     
       
   209     for(int i = 0; i < sortOrders.count(); i++)
       
   210     {
       
   211         columnName(column, sortOrders.at(i).detailDefinitionName(), sortOrders.at(i).detailFieldName());
       
   212       
       
   213         if(!column.isEmpty())
       
   214         {
       
   215             if(first)
       
   216             {
       
   217                 sqlQuery += " ORDER BY";
       
   218                 first = false;        
       
   219             }
       
   220           
       
   221             else
       
   222             {
       
   223                 sqlQuery += ",";
       
   224             }
       
   225             
       
   226             //use the display label if the name is null, ignore case
       
   227             sqlQuery += " CASE WHEN " + column + " ISNULL THEN \'"+ displayLabel.unNamned().toLower() + "\' ELSE lower(" + column + ") END";
       
   228             
       
   229             if(sortOrders.at(i).direction() == Qt::AscendingOrder)
       
   230             {
       
   231                 sqlQuery += " ASC";
       
   232             }
       
   233                 
       
   234             else if(sortOrders.at(i).direction() == Qt::DescendingOrder)
       
   235             {
       
   236                 sqlQuery += " DESC";
       
   237             }
       
   238         }
       
   239     }
       
   240 }
       
   241 
       
   242 /*!
       
   243  * Retrieve a column name
       
   244  *
       
   245  * \a columnName to be saved the column name if found
       
   246  * \a detailDefinitionName of the detail to fetch column name for
       
   247  * \a detailFieldName of the detail to fetch column name for
       
   248  */
       
   249 void CntSymbianFilterSqlHelper::columnName( QString &columnName, const QString &detailDefinitionName, const QString & detailFieldName)
       
   250 {
       
   251     columnName = "";
       
   252 
       
   253     //Name detail
       
   254     if(detailDefinitionName == QContactName::DefinitionName)
       
   255     {
       
   256         if(detailFieldName == QContactName::FieldFirst)
       
   257         {
       
   258             columnName = "first_name";
       
   259         }
       
   260         
       
   261         else if(detailFieldName == QContactName::FieldLast)
       
   262         {
       
   263             columnName = "last_name";
       
   264         }
       
   265     }
       
   266     
       
   267     //Organization
       
   268     else if(detailDefinitionName == QContactOrganization::DefinitionName)
       
   269     {
       
   270         if(detailFieldName == QContactOrganization::FieldName)
       
   271         {
       
   272             columnName = "company_name";
       
   273         }
       
   274     }
       
   275 }
       
   276 
       
   277 /*!
       
   278  * converts complex filter into simple filters
       
   279  *
       
   280  * \a filter The simple/complex QContactFilter passed .
       
   281  * \a sqlQuery The sql query that would be formed
       
   282  * \a error On return, contains the possible error.
       
   283  */
       
   284 void CntSymbianFilterSqlHelper::createSqlQuery(const QContactFilter& filter,
       
   285                                                  QString& sqlQuery,
       
   286                                                  QContactManager::Error& error)
       
   287 {
       
   288     //Check if it is a single filter
       
   289     bool IsOneLevelFilter  = isSingleFilter(filter);
       
   290     if(IsOneLevelFilter) {
       
   291         //Single Filter, get the sql query here
       
   292         updateSqlQueryForSingleFilter(filter,sqlQuery,error);
       
   293     } else {
       
   294         // We have multiple filters. Combine these to form correct query
       
   295         // Not supported yet
       
   296         error = QContactManager::NotSupportedError;
       
   297     }
       
   298 }
       
   299 
       
   300 /*!
       
   301  * Checks if the given filter is a single filter or combination of filters
       
   302  *
       
   303  * \a filter The QContactFilter to be used.
       
   304  * \return True if the filters is single filter
       
   305  */
       
   306 
       
   307 bool CntSymbianFilterSqlHelper::isSingleFilter(const QContactFilter& singlefilter) const
       
   308 {
       
   309 
       
   310     bool returnValue = false;
       
   311     switch (singlefilter.type()) {
       
   312         case QContactFilter::ContactDetailFilter:
       
   313         case QContactFilter::InvalidFilter :
       
   314         case QContactFilter::ContactDetailRangeFilter:
       
   315         case QContactFilter::ChangeLogFilter:
       
   316         case QContactFilter::DefaultFilter:
       
   317                         //All are single filters, return True
       
   318                         returnValue = true;
       
   319                         break;
       
   320         case QContactFilter::ActionFilter:
       
   321         case QContactFilter::IntersectionFilter:
       
   322         case QContactFilter::UnionFilter:
       
   323 
       
   324                         //All these are multiple filters
       
   325                         returnValue = false;
       
   326                         break;
       
   327         default:
       
   328                         returnValue = false;
       
   329                         break;
       
   330     };
       
   331     return returnValue;
       
   332 }
       
   333 
       
   334 /*!
       
   335  * Updates the input sql query for single filter
       
   336  *
       
   337  * \a filter The QContactFilter to be used.
       
   338  * \a sqlQuery The sql query that would be updated
       
   339  * \a error On return, contains the possible error
       
   340  */
       
   341 void  CntSymbianFilterSqlHelper::updateSqlQueryForSingleFilter( const QContactFilter& filter,
       
   342                                                                 QString& sqlQuery,
       
   343                                                                 QContactManager::Error& error)
       
   344 {
       
   345     switch (filter.type()) {
       
   346            case QContactFilter::InvalidFilter :
       
   347            {
       
   348                // Not supported yet
       
   349                error = QContactManager::NotSupportedError;
       
   350                break;
       
   351            }
       
   352            case QContactFilter::ContactDetailFilter:
       
   353            {
       
   354                const QContactDetailFilter detailFilter(filter);
       
   355                
       
   356                //display label
       
   357                if (detailFilter.detailDefinitionName() == QContactDisplayLabel::DefinitionName)
       
   358                {
       
   359                    CntDisplayLabelSqlFilter displayLabelFilter;
       
   360                    displayLabelFilter.createSqlQuery(detailFilter,sqlQuery,error);
       
   361                }
       
   362                
       
   363                //type
       
   364                else if(detailFilter.detailDefinitionName() == QContactType::DefinitionName)
       
   365                {
       
   366                    if(detailFilter.value().toString() == QContactType::TypeContact)
       
   367                        sqlQuery = "SELECT contact_id FROM contact WHERE (type_flags>>24)=0";
       
   368                    else if(detailFilter.value().toString() == QContactType::TypeGroup)
       
   369                        sqlQuery = "SELECT contact_id FROM contact WHERE (type_flags>>24)=3";
       
   370                }
       
   371                
       
   372                //everything else
       
   373                else
       
   374                {
       
   375                    updateSqlQueryForDetailFilter(filter,sqlQuery,error);
       
   376                }
       
   377                
       
   378                break;
       
   379            }
       
   380            case QContactFilter::ContactDetailRangeFilter:
       
   381                        // Not supported yet
       
   382                        error = QContactManager::NotSupportedError;
       
   383                        break;
       
   384 
       
   385            case QContactFilter::ChangeLogFilter:
       
   386                        // Not supported yet
       
   387                        error = QContactManager::NotSupportedError;
       
   388                        break;
       
   389            case QContactFilter::DefaultFilter:
       
   390                        sqlQuery = "SELECT DISTINCT contact_id FROM contact WHERE (type_flags>>24)=0 OR (type_flags>>24)=3"; 
       
   391                        error = QContactManager::NoError;
       
   392                        break;
       
   393            case QContactFilter::ActionFilter:
       
   394            case QContactFilter::IntersectionFilter:
       
   395            case QContactFilter::UnionFilter:
       
   396                        //All these are multiple filters
       
   397                        // Not supported yet
       
   398                        error = QContactManager::NotSupportedError;
       
   399                        break;
       
   400            default:
       
   401                        //Some Unknow filter value
       
   402                        // Not supported
       
   403                        error = QContactManager::NotSupportedError;
       
   404                        break;
       
   405     };
       
   406     if( error != QContactManager::NoError)
       
   407         {
       
   408         sqlQuery = "";
       
   409         }
       
   410 }
       
   411 
       
   412 /*!
       
   413  * Updates the input sql query for detail filter
       
   414  *
       
   415  * \a filter The QContactFilter to be used.
       
   416  * \a sqlQuery The sql query that would be updated
       
   417  * \a error On return, contains the possible error
       
   418  */
       
   419 void CntSymbianFilterSqlHelper::updateSqlQueryForDetailFilter(const QContactFilter& filter,
       
   420                                                               QString& sqlQuery,
       
   421                                                               QContactManager::Error& error)
       
   422 {
       
   423 
       
   424 
       
   425     // cast the filter into detail filter
       
   426     const QContactDetailFilter detailFilter(filter);
       
   427 
       
   428     QString sqlWhereClause =  Space  + " WHERE ";
       
   429 
       
   430     //Get the table name and the column name
       
   431     bool isSubType;
       
   432     QString columnName;
       
   433     QString tableName;
       
   434 
       
   435     //Check for phonenumber. Special handling needed
       
   436     if(detailFilter.detailDefinitionName() == QContactPhoneNumber::DefinitionName){
       
   437         isPhoneNumberSearchforDetailFilter = true;
       
   438         error = QContactManager::NoError;
       
   439         return;
       
   440     }
       
   441 
       
   442     getSqlDbTableAndColumnNameforDetailFilter(detailFilter,isSubType,tableName,columnName);
       
   443 
       
   444     //return if tableName is empty
       
   445     if(tableName == "" ){
       
   446         error = QContactManager::NotSupportedError;
       
   447         return;
       
   448     }
       
   449 
       
   450     //check columnName
       
   451     if(columnName == "") {
       
   452         error = QContactManager::NotSupportedError;
       
   453         return;
       
   454     }
       
   455     else if(isSubType) {
       
   456         sqlWhereClause += columnName;
       
   457         sqlWhereClause += " NOT NULL ";
       
   458     }
       
   459     else {
       
   460 
       
   461         sqlWhereClause += Space + columnName + Space ;
       
   462         QString fieldToUpdate;
       
   463         //Update the value depending on the match flag
       
   464         updateFieldForDeatilFilterMatchFlag(detailFilter,fieldToUpdate,error);
       
   465         sqlWhereClause +=  fieldToUpdate;
       
   466     }
       
   467 
       
   468 
       
   469     //Create the sql query
       
   470     sqlQuery += "SELECT DISTINCT contact_id FROM " + Space + tableName + Space + sqlWhereClause;
       
   471 
       
   472 
       
   473 }
       
   474 
       
   475 /*!
       
   476  * Converts filed id to column name of the database table.
       
   477  * QContactManager::contacts function.
       
   478  *
       
   479  * \a fieldId field id representing the detail field name
       
   480  * \a sqlDbTableColumnName On return,contains the column name in the database
       
   481  */
       
   482 void CntSymbianFilterSqlHelper::updateFieldForDeatilFilterMatchFlag(
       
   483                                                     const QContactDetailFilter& filter,
       
   484                                                     QString& fieldToUpdate ,
       
   485                                                     QContactManager::Error& error) const
       
   486 {
       
   487     // Modify the filed depending on the query
       
   488     switch(filter.matchFlags())
       
   489         {
       
   490             case QContactFilter::MatchExactly:
       
   491                 {
       
   492                 // Pattern for MatchExactly:
       
   493                 // " ='xyz'"
       
   494                 fieldToUpdate = Space + EqualTo + SingleQuote
       
   495                                + filter.value().toString() + SingleQuote;
       
   496                 error = QContactManager::NoError;
       
   497                 break;
       
   498                 }
       
   499             case QContactFilter::MatchContains:
       
   500                 {
       
   501                 // Pattern for MatchContains:
       
   502                 // " LIKE '%xyz%'"
       
   503                 fieldToUpdate = Space + SqlLike + Space + SingleQuote + PercentSign
       
   504                                 + filter.value().toString() + PercentSign + SingleQuote ;
       
   505                 error = QContactManager::NoError;
       
   506                 break;
       
   507                 }
       
   508             case QContactFilter::MatchStartsWith:
       
   509                 {
       
   510                 // Pattern for MatchStartsWith:
       
   511                 // " LIKE 'xyz%'"
       
   512                 fieldToUpdate = Space + SqlLike + Space + SingleQuote
       
   513                                +  filter.value().toString() + PercentSign + SingleQuote  ;
       
   514                 error = QContactManager::NoError;
       
   515                 break;
       
   516                 }
       
   517             case QContactFilter::MatchEndsWith:
       
   518                 {
       
   519                 // Pattern for MatchEndsWith:
       
   520                 // " LIKE '%xyz'"
       
   521                 fieldToUpdate = Space + SqlLike + Space + SingleQuote + PercentSign
       
   522                               + filter.value().toString() + SingleQuote ;
       
   523                 error = QContactManager::NoError;
       
   524                 break;
       
   525                 }
       
   526             case QContactFilter::MatchFixedString:
       
   527                 {
       
   528                 error = QContactManager::NotSupportedError;
       
   529                 break;
       
   530                 }
       
   531             case QContactFilter::MatchCaseSensitive:
       
   532                 {
       
   533                 error = QContactManager::NotSupportedError;
       
   534                 break;
       
   535                 }
       
   536             default:
       
   537                 {
       
   538                 error = QContactManager::NotSupportedError;
       
   539                 break;
       
   540                 }
       
   541         }
       
   542 }
       
   543 
       
   544 /*!
       
   545  * Converts filed id to column name of the database table.
       
   546  * QContactManager::contacts function.
       
   547  *
       
   548  * \a fieldId field id representing the detail field name
       
   549  * \a sqlDbTableColumnName On return,contains the column name in the database
       
   550  */
       
   551 void CntSymbianFilterSqlHelper::getSqlDbTableAndColumnNameforDetailFilter(
       
   552                                                     const QContactDetailFilter& detailFilter ,
       
   553                                                     bool& isSubType,
       
   554                                                     QString& tableName,
       
   555                                                     QString& columnName )
       
   556 {
       
   557 
       
   558     //Get the field id for the detail field name
       
   559     CntTransformContact transformContact;
       
   560     quint32 fieldId  = transformContact.GetIdForDetailL(detailFilter, isSubType);
       
   561 
       
   562     //check contacts table
       
   563     columnName = "";
       
   564     tableName = "";
       
   565 
       
   566     if (contactsTableIdColumNameMapping.contains(fieldId)){
       
   567          columnName = contactsTableIdColumNameMapping.value(fieldId);
       
   568          tableName = "contact";
       
   569      }
       
   570 
       
   571     if( ("" == columnName)  || ("" == tableName)){
       
   572         //Search comm Addr table
       
   573         if (commAddrTableIdColumNameMapping.contains(fieldId)){
       
   574                 // communication address table has slightly differnt format, so we make the column name as
       
   575                 //  "type = <type> and value "
       
   576                 int typeval = commAddrTableIdColumNameMapping.value(fieldId) ;
       
   577                 columnName = Space + "TYPE = ";
       
   578                 columnName.append('0'+ typeval)
       
   579                 + typeval + Space;
       
   580                 columnName += " and value " ;
       
   581                 tableName = "comm_addr";
       
   582              }
       
   583 
       
   584     }
       
   585 }
       
   586 
       
   587 QList<QContactLocalId> CntSymbianFilterSqlHelper::HandlePhonenumberDetailFilter(const QContactDetailFilter detailFilter)
       
   588     {
       
   589     QList<QContactLocalId> matches;
       
   590 
       
   591     if(detailFilter.detailDefinitionName() == QContactPhoneNumber::DefinitionName){
       
   592 
       
   593     // Phone numbers need separate handling
       
   594             if ((filterSupportLevel(detailFilter) == CntAbstractContactFilter::Supported
       
   595                  || filterSupportLevel(detailFilter) == CntAbstractContactFilter::SupportedPreFilterOnly))
       
   596             {
       
   597                 QString number((detailFilter.value()).toString());
       
   598                 TPtrC commPtr(reinterpret_cast<const TUint16*>(number.utf16()));
       
   599 
       
   600                 TInt matchLength(KDefaultMatchLength);
       
   601                 // no need to propagate error, we can use the default match length
       
   602                 TRAP_IGNORE(getMatchLengthL(matchLength));
       
   603 
       
   604                 //cal the search
       
   605                 CContactIdArray* idArray(0);
       
   606                 TInt err = searchPhoneNumbers(idArray, commPtr, matchLength);
       
   607                 if( idArray && (err == KErrNone)){
       
   608                     // copy the matching contact ids
       
   609                     for(int i(0); i < idArray->Count(); i++) {
       
   610                         matches.append(QContactLocalId((*idArray)[i]));
       
   611                     }
       
   612                     delete idArray;
       
   613                 }
       
   614                 else{
       
   615                     //CntSymbianTransformError::transformError(err, error);
       
   616                     }
       
   617             }
       
   618 
       
   619 
       
   620     }
       
   621     return matches;
       
   622 
       
   623     }
       
   624 /*!
       
   625  * The contact database version implementation for
       
   626  * QContactManager::filterSupported function. The possible return values are
       
   627  * Supported, NotSupported and SupportedPreFilterOnly. Supported means that
       
   628  * the filtering is implemented directly by the underlying database.
       
   629  * NotSupported means that CntSymbianFilterDbms::contacts will return an
       
   630  * error. And SupportedPreFilterOnly means that the filter is not supported,
       
   631  * but the CntSymbianFilterDbms::contacts will act like the filter was
       
   632  * supported. This means that the client must filter the pre-filtered set of
       
   633  * contacts to see if there are false positives included. Note that in some
       
   634  * cases the pre-filtering is not very effective.
       
   635  *
       
   636  * \a filter The QContactFilter to be checked.
       
   637  * \a return Supported in case the filter is supported. NotSupported in case
       
   638  * the filter is not supported. returns
       
   639  *
       
   640  */
       
   641 CntAbstractContactFilter::FilterSupport CntSymbianFilterSqlHelper::filterSupportLevel(const QContactFilter& filter)
       
   642 {
       
   643     CntAbstractContactFilter::FilterSupport filterSupported(CntAbstractContactFilter::NotSupported);
       
   644     switch (filter.type()) {
       
   645             case QContactFilter::DefaultFilter: //default filter == no filter
       
   646                 {
       
   647                 filterSupported = CntAbstractContactFilter::Supported;
       
   648                 break;
       
   649                 }
       
   650             case QContactFilter::ContactDetailFilter:
       
   651             	{
       
   652                 const QContactDetailFilter &detailFilter = static_cast<const QContactDetailFilter &>(filter);
       
   653                 filterSupported = checkIfDetailFilterSupported(detailFilter);
       
   654                 break;
       
   655                 }
       
   656             case QContactFilter::InvalidFilter :
       
   657             case QContactFilter::ContactDetailRangeFilter:
       
   658             case QContactFilter::ChangeLogFilter:
       
   659             case QContactFilter::ActionFilter:
       
   660             case QContactFilter::IntersectionFilter:
       
   661             case QContactFilter::UnionFilter:
       
   662             case QContactFilter::RelationshipFilter: 
       
   663             default:
       
   664                     filterSupported = CntAbstractContactFilter::NotSupported;
       
   665                     break;
       
   666         }
       
   667     return filterSupported;
       
   668 }
       
   669 CntAbstractContactFilter::FilterSupport CntSymbianFilterSqlHelper::checkIfDetailFilterSupported
       
   670                                                                     (const QContactDetailFilter& detailFilter) const
       
   671 {
       
   672 
       
   673         CntAbstractContactFilter::FilterSupport filterSupported(CntAbstractContactFilter::NotSupported);
       
   674         //Get the match flags
       
   675         QContactFilter::MatchFlags matchFlags = detailFilter.matchFlags();
       
   676         // Phone numbers
       
   677         if (detailFilter.detailDefinitionName() == QContactPhoneNumber::DefinitionName) {
       
   678             if (matchFlags == QContactFilter::MatchEndsWith){
       
   679                 filterSupported = CntAbstractContactFilter::Supported;
       
   680             }
       
   681             else if (matchFlags == QContactFilter::MatchExactly){
       
   682                 filterSupported = CntAbstractContactFilter::SupportedPreFilterOnly;
       
   683             }
       
   684         }
       
   685         // Names , Email,Sip address
       
   686         else if ( detailFilter.detailDefinitionName() == QContactName::DefinitionName ||
       
   687                   detailFilter.detailDefinitionName() == QContactEmailAddress::DefinitionName ||
       
   688                   detailFilter.detailDefinitionName() == QContactOnlineAccount::DefinitionName ||
       
   689                   detailFilter.detailDefinitionName() == QContactDisplayLabel::DefinitionName ||
       
   690                   detailFilter.detailDefinitionName() == QContactType::DefinitionName){
       
   691                if (  (matchFlags == QContactFilter::MatchContains)|| (matchFlags == QContactFilter::MatchStartsWith)||
       
   692                      (matchFlags == QContactFilter::MatchEndsWith)|| (matchFlags == QContactFilter::MatchExactly)){
       
   693                 filterSupported = CntAbstractContactFilter::Supported;
       
   694                }
       
   695                if(matchFlags == QContactFilter::MatchKeypadCollation)
       
   696                       filterSupported = CntAbstractContactFilter::Supported;
       
   697         }
       
   698         return filterSupported;
       
   699 
       
   700 }
       
   701 /*
       
   702  * Get the match length setting. Digits to be used in matching (counted from
       
   703  * right).
       
   704  */
       
   705 void CntSymbianFilterSqlHelper::getMatchLengthL(TInt& matchLength)
       
   706 {
       
   707     //Get number of digits used to match
       
   708     CRepository* repository = CRepository::NewL(KCRUidTelConfiguration);
       
   709     CleanupStack::PushL(repository);
       
   710     User::LeaveIfError(repository->Get(KTelMatchDigits, matchLength));
       
   711     CleanupStack::PopAndDestroy(repository);
       
   712 }
       
   713 
       
   714 /*
       
   715  * Find contacts based on a phone number.
       
   716  * \a idArray On return contains the ids of the contacts that match the phonenumber.
       
   717  * \a phoneNumber The phone number to match
       
   718  * \a matchLength Match length; digits from right.
       
   719  */
       
   720 TInt CntSymbianFilterSqlHelper::searchPhoneNumbers(
       
   721         CContactIdArray*& idArray,
       
   722         const TDesC& phoneNumber,
       
   723         const TInt matchLength)
       
   724 {
       
   725     CContactIdArray* idArrayTmp(0);
       
   726     TRAPD( err, idArrayTmp = m_contactDatabase.MatchPhoneNumberL(phoneNumber, matchLength));
       
   727     if(err == KErrNone){
       
   728        idArray = idArrayTmp;
       
   729     }
       
   730     return 0;
       
   731 }