1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_connectivity.hxx" 26 27 #include "KStatement.hxx" 28 #include "KConnection.hxx" 29 #include "KDriver.hxx" 30 #include "KResultSet.hxx" 31 #include "KResultSetMetaData.hxx" 32 #include "kcondition.hxx" 33 #include "korder.hxx" 34 #include "TConnection.hxx" 35 #include <connectivity/dbexception.hxx> 36 #include "resource/kab_res.hrc" 37 #include "resource/sharedresources.hxx" 38 39 40 #if OSL_DEBUG_LEVEL > 0 41 # define OUtoCStr( x ) ( ::rtl::OUStringToOString ( (x), RTL_TEXTENCODING_ASCII_US).getStr()) 42 #else /* OSL_DEBUG_LEVEL */ 43 # define OUtoCStr( x ) ("dummy") 44 #endif /* OSL_DEBUG_LEVEL */ 45 46 using namespace connectivity::kab; 47 using namespace com::sun::star::uno; 48 using namespace com::sun::star::lang; 49 using namespace com::sun::star::beans; 50 using namespace com::sun::star::sdbc; 51 using namespace com::sun::star::sdbcx; 52 using namespace com::sun::star::container; 53 using namespace com::sun::star::io; 54 using namespace com::sun::star::util; 55 56 namespace 57 { 58 void lcl_throwError(sal_uInt16 _nErrorId) 59 { 60 ::connectivity::SharedResources aResources; 61 const ::rtl::OUString sError( aResources.getResourceString(_nErrorId) ); 62 ::dbtools::throwGenericSQLException(sError,NULL); 63 } 64 } 65 66 IMPLEMENT_SERVICE_INFO(KabStatement, "com.sun.star.sdbc.drivers.KabStatement", "com.sun.star.sdbc.Statement"); 67 //------------------------------------------------------------------------------ 68 KabCommonStatement::KabCommonStatement(KabConnection* _pConnection ) 69 : KabCommonStatement_BASE(m_aMutex), 70 OPropertySetHelper(KabCommonStatement_BASE::rBHelper), 71 m_aParser(_pConnection->getDriver()->getMSFactory()), 72 m_aSQLIterator(_pConnection, _pConnection->createCatalog()->getTables(), m_aParser, NULL ), 73 m_pParseTree(NULL), 74 m_pConnection(_pConnection), 75 rBHelper(KabCommonStatement_BASE::rBHelper) 76 { 77 m_pConnection->acquire(); 78 } 79 // ----------------------------------------------------------------------------- 80 KabCommonStatement::~KabCommonStatement() 81 { 82 } 83 // ----------------------------------------------------------------------------- 84 void KabCommonStatement::disposing() 85 { 86 KabCommonStatement_BASE::disposing(); 87 } 88 // ----------------------------------------------------------------------------- 89 void KabCommonStatement::resetParameters() const throw(::com::sun::star::sdbc::SQLException) 90 { 91 lcl_throwError(STR_PARA_ONLY_PREPARED); 92 } 93 // ----------------------------------------------------------------------------- 94 void KabCommonStatement::getNextParameter(::rtl::OUString &) const throw(::com::sun::star::sdbc::SQLException) 95 { 96 lcl_throwError(STR_PARA_ONLY_PREPARED); 97 } 98 // ----------------------------------------------------------------------------- 99 KabCondition *KabCommonStatement::analyseWhereClause(const OSQLParseNode *pParseNode) const throw(SQLException) 100 { 101 if (pParseNode->count() == 3) 102 { 103 const OSQLParseNode *pLeft = pParseNode->getChild(0), 104 *pMiddle = pParseNode->getChild(1), 105 *pRight = pParseNode->getChild(2); 106 107 // WHERE ( ... ) ? 108 if (SQL_ISPUNCTUATION(pLeft, "(") && SQL_ISPUNCTUATION(pRight, ")")) 109 { 110 return analyseWhereClause(pMiddle); 111 } 112 else if (SQL_ISRULE(pParseNode, comparison_predicate)) 113 { 114 if (pLeft->isToken() && pRight->isToken()) 115 { 116 switch (pMiddle->getNodeType()) 117 { 118 case SQL_NODE_EQUAL: 119 // WHERE 0 = 1 120 return new KabConditionConstant(pLeft->getTokenValue() == pRight->getTokenValue()); 121 122 case SQL_NODE_NOTEQUAL: 123 // WHERE 0 <> 1 124 // (might not be correct SQL... don't care, handling anyway) 125 return new KabConditionConstant(pLeft->getTokenValue() != pRight->getTokenValue()); 126 127 default: 128 break; 129 } 130 } 131 else if (SQL_ISRULE(pLeft, column_ref)) 132 { 133 ::rtl::OUString sColumnName, 134 sTableRange; 135 136 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange); 137 138 if (pRight->isToken() || SQL_ISRULE(pRight, parameter)) 139 { 140 ::rtl::OUString sMatchString; 141 142 if (pRight->isToken()) // WHERE Name = 'Doe' 143 sMatchString = pRight->getTokenValue(); 144 else if (SQL_ISRULE(pRight, parameter)) // WHERE Name = ? 145 getNextParameter(sMatchString); 146 147 switch (pMiddle->getNodeType()) 148 { 149 case SQL_NODE_EQUAL: 150 // WHERE Name = 'Smith' 151 return new KabConditionEqual(sColumnName, sMatchString); 152 153 case SQL_NODE_NOTEQUAL: 154 // WHERE Name <> 'Jones' 155 return new KabConditionDifferent(sColumnName, sMatchString); 156 157 default: 158 break; 159 } 160 } 161 } 162 } 163 else if (SQL_ISRULE(pParseNode, search_condition)) 164 { 165 if (SQL_ISTOKEN(pMiddle, OR)) 166 { 167 // WHERE Name = 'Smith' OR Name = 'Jones' 168 return new KabConditionOr( 169 analyseWhereClause(pLeft), 170 analyseWhereClause(pRight)); 171 } 172 } 173 else if (SQL_ISRULE(pParseNode, boolean_term)) 174 { 175 if (SQL_ISTOKEN(pMiddle, AND)) 176 { 177 // WHERE Name = 'Smith' AND "Given Name" = 'Peter' 178 return new KabConditionAnd( 179 analyseWhereClause(pLeft), 180 analyseWhereClause(pRight)); 181 } 182 } 183 } 184 else if (SQL_ISRULE(pParseNode, test_for_null) || SQL_ISRULE(pParseNode, like_predicate)) 185 { 186 const OSQLParseNode *pLeft = pParseNode->getChild(0); 187 const OSQLParseNode* pPart2 = pParseNode->getChild(1); 188 const OSQLParseNode *pMiddleLeft = pPart2->getChild(0), 189 *pMiddleRight = pPart2->getChild(1), 190 *pRight = pPart2->getChild(2); 191 192 if (SQL_ISRULE(pParseNode, test_for_null)) 193 { 194 if (SQL_ISRULE(pLeft, column_ref) && 195 SQL_ISTOKEN(pMiddleLeft, IS) && 196 SQL_ISTOKEN(pRight, NULL)) 197 { 198 ::rtl::OUString sColumnName, 199 sTableRange; 200 201 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange); 202 203 if (SQL_ISTOKEN(pMiddleRight, NOT)) 204 { 205 // WHERE "Mobile Phone" IS NOT NULL 206 return new KabConditionNotNull(sColumnName); 207 } 208 else 209 { 210 // WHERE "Mobile Phone" IS NULL 211 return new KabConditionNull(sColumnName); 212 } 213 } 214 } 215 else if (SQL_ISRULE(pParseNode, like_predicate)) 216 { 217 if (SQL_ISRULE(pLeft, column_ref)) 218 { 219 ::rtl::OUString sColumnName, 220 sTableRange; 221 222 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange); 223 224 if (pMiddleRight->isToken() || SQL_ISRULE(pMiddleRight, parameter)) 225 { 226 ::rtl::OUString sMatchString; 227 228 if (pMiddleRight->isToken()) // WHERE Name LIKE 'Sm%' 229 sMatchString = pMiddleRight->getTokenValue(); 230 else if (SQL_ISRULE(pMiddleRight, parameter)) // WHERE Name LIKE ? 231 getNextParameter(sMatchString); 232 233 return new KabConditionSimilar(sColumnName, sMatchString); 234 } 235 } 236 } 237 } 238 239 lcl_throwError(STR_QUERY_TOO_COMPLEX); 240 241 // Unreachable: 242 OSL_ASSERT(false); 243 return 0; 244 } 245 // ----------------------------------------------------------------------------- 246 KabOrder *KabCommonStatement::analyseOrderByClause(const OSQLParseNode *pParseNode) const throw(SQLException) 247 { 248 if (SQL_ISRULE(pParseNode, ordering_spec_commalist)) 249 { 250 KabComplexOrder *list = new KabComplexOrder(); 251 sal_uInt32 n = pParseNode->count(); 252 253 // Iterate through the ordering columns 254 for (sal_uInt32 i = 0; i < n; i++) 255 { 256 list->addOrder 257 (analyseOrderByClause(pParseNode->getChild(i))); 258 } 259 260 return list; 261 } 262 else if (SQL_ISRULE(pParseNode, ordering_spec)) 263 { 264 if (pParseNode->count() == 2) 265 { 266 OSQLParseNode* pColumnRef = pParseNode->getChild(0); 267 OSQLParseNode* pAscendingDescending = pParseNode->getChild(1); 268 269 if (SQL_ISRULE(pColumnRef, column_ref)) 270 { 271 if (pColumnRef->count() == 3) 272 pColumnRef = pColumnRef->getChild(2); 273 274 if (pColumnRef->count() == 1) 275 { 276 ::rtl::OUString sColumnName = 277 pColumnRef->getChild(0)->getTokenValue(); 278 sal_Bool bAscending = 279 SQL_ISTOKEN(pAscendingDescending, DESC)? 280 sal_False: 281 sal_True; 282 283 return new KabSimpleOrder(sColumnName, bAscending); 284 } 285 } 286 } 287 } 288 lcl_throwError(STR_QUERY_TOO_COMPLEX); 289 // Unreachable: 290 OSL_ASSERT(false); 291 return 0; 292 } 293 //------------------------------------------------------------------------------ 294 sal_Bool KabCommonStatement::isTableKnown(KabResultSet *pResult) const 295 { 296 // can handle requests like SELECT * FROM addresses addresses 297 // but cannot handle requests like SELECT * FROM addresses persons 298 if (m_aSQLIterator.getTables().size() != 1) 299 return sal_False; 300 301 if (m_aSQLIterator.getTables().begin()->first != pResult->getMetaData()->getTableName(0)) 302 return sal_False; 303 304 return sal_True; 305 } 306 //------------------------------------------------------------------------------ 307 void KabCommonStatement::setKabFields(KabResultSet *pResult) const throw(SQLException) 308 { 309 ::vos::ORef<connectivity::OSQLColumns> xColumns; // selected columns 310 KabResultSetMetaData *pMeta; // meta information - holds the list of KAddressBook fields 311 312 xColumns = m_aSQLIterator.getSelectColumns(); 313 if (!xColumns.isValid()) 314 { 315 lcl_throwError(STR_INVALID_COLUMN_SELECTION); 316 } 317 pMeta = static_cast<KabResultSetMetaData *>(pResult->getMetaData().get()); 318 pMeta->setKabFields(xColumns); 319 } 320 // ------------------------------------------------------------------------- 321 void KabCommonStatement::selectAddressees(KabResultSet *pResult) const throw(SQLException) 322 { 323 const OSQLParseNode *pParseNode; 324 KabCondition *pCondition; 325 326 pParseNode = m_aSQLIterator.getWhereTree(); 327 if (pParseNode != NULL) 328 { 329 if (SQL_ISRULE(pParseNode, where_clause)) 330 { 331 resetParameters(); 332 pParseNode = pParseNode->getChild(1); 333 pCondition = analyseWhereClause(pParseNode); 334 if (pCondition->isAlwaysTrue()) 335 pResult->allKabAddressees(); 336 else if (!pCondition->isAlwaysFalse()) 337 pResult->someKabAddressees(pCondition); 338 delete pCondition; 339 return; 340 } 341 } 342 343 // no WHERE clause: get all rows 344 pResult->allKabAddressees(); 345 } 346 // ------------------------------------------------------------------------- 347 void KabCommonStatement::sortAddressees(KabResultSet *pResult) const throw(SQLException) 348 { 349 const OSQLParseNode *pParseNode; 350 KabOrder *pOrder; 351 352 pParseNode = m_aSQLIterator.getOrderTree(); 353 if (pParseNode != NULL) 354 { 355 if (SQL_ISRULE(pParseNode, opt_order_by_clause)) 356 { 357 pParseNode = pParseNode->getChild(2); 358 pOrder = analyseOrderByClause(pParseNode); 359 pResult->sortKabAddressees(pOrder); 360 delete pOrder; 361 } 362 } 363 } 364 //----------------------------------------------------------------------------- 365 Any SAL_CALL KabCommonStatement::queryInterface( const Type & rType ) throw(RuntimeException) 366 { 367 Any aRet = KabCommonStatement_BASE::queryInterface(rType); 368 if (!aRet.hasValue()) 369 aRet = OPropertySetHelper::queryInterface(rType); 370 return aRet; 371 } 372 // ------------------------------------------------------------------------- 373 Sequence< Type > SAL_CALL KabCommonStatement::getTypes( ) throw(RuntimeException) 374 { 375 ::cppu::OTypeCollection aTypes( ::getCppuType( (const Reference< XMultiPropertySet > *)0 ), 376 ::getCppuType( (const Reference< XFastPropertySet > *)0 ), 377 ::getCppuType( (const Reference< XPropertySet > *)0 )); 378 379 return comphelper::concatSequences(aTypes.getTypes(),KabCommonStatement_BASE::getTypes()); 380 } 381 // ------------------------------------------------------------------------- 382 void SAL_CALL KabCommonStatement::cancel( ) throw(RuntimeException) 383 { 384 ::osl::MutexGuard aGuard( m_aMutex ); 385 386 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed); 387 // cancel the current sql statement 388 } 389 // ------------------------------------------------------------------------- 390 void SAL_CALL KabCommonStatement::close( ) throw(SQLException, RuntimeException) 391 { 392 { 393 ::osl::MutexGuard aGuard( m_aMutex ); 394 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed); 395 396 } 397 dispose(); 398 } 399 // ------------------------------------------------------------------------- 400 sal_Bool SAL_CALL KabCommonStatement::execute( 401 const ::rtl::OUString& sql ) throw(SQLException, RuntimeException) 402 { 403 ::osl::MutexGuard aGuard( m_aMutex ); 404 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed); 405 406 Reference< XResultSet > xRS = executeQuery(sql); 407 408 return xRS.is(); 409 } 410 // ------------------------------------------------------------------------- 411 Reference< XResultSet > SAL_CALL KabCommonStatement::executeQuery( 412 const ::rtl::OUString& sql ) throw(SQLException, RuntimeException) 413 { 414 ::osl::MutexGuard aGuard( m_aMutex ); 415 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed); 416 417 OSL_TRACE("KDE Address book - SQL Request: %s", OUtoCStr(sql)); 418 419 KabResultSet* pResult = new KabResultSet(this); 420 Reference< XResultSet > xRS = pResult; 421 ::rtl::OUString aErr; 422 423 m_pParseTree = m_aParser.parseTree(aErr, sql); 424 if (m_pParseTree == NULL) 425 throw SQLException(aErr, *this, aErr, 0, Any()); 426 427 m_aSQLIterator.setParseTree(m_pParseTree); 428 m_aSQLIterator.traverseAll(); 429 switch (m_aSQLIterator.getStatementType()) 430 { 431 case SQL_STATEMENT_SELECT: 432 if (isTableKnown(pResult)) // FROM which table ? 433 { 434 setKabFields(pResult); // SELECT which columns ? 435 selectAddressees(pResult); // WHERE which condition ? 436 sortAddressees(pResult); // ORDER BY which columns ? 437 // To be continued: DISTINCT 438 // etc... 439 } 440 break; 441 442 default: 443 // To be continued: UPDATE 444 // DELETE 445 // etc... 446 lcl_throwError(STR_QUERY_TOO_COMPLEX); 447 } 448 449 return xRS; 450 } 451 // ------------------------------------------------------------------------- 452 Reference< XConnection > SAL_CALL KabCommonStatement::getConnection( ) throw(SQLException, RuntimeException) 453 { 454 ::osl::MutexGuard aGuard( m_aMutex ); 455 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed); 456 457 // just return our connection here 458 return (Reference< XConnection >) m_pConnection; 459 } 460 // ------------------------------------------------------------------------- 461 sal_Int32 SAL_CALL KabCommonStatement::executeUpdate( const ::rtl::OUString& ) throw(SQLException, RuntimeException) 462 { 463 ::osl::MutexGuard aGuard( m_aMutex ); 464 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed); 465 466 // the return values gives information about how many rows are affected by executing the sql statement 467 return 0; 468 } 469 // ------------------------------------------------------------------------- 470 Any SAL_CALL KabCommonStatement::getWarnings( ) throw(SQLException, RuntimeException) 471 { 472 ::osl::MutexGuard aGuard( m_aMutex ); 473 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed); 474 475 return makeAny(m_aLastWarning); 476 } 477 // ------------------------------------------------------------------------- 478 void SAL_CALL KabCommonStatement::clearWarnings( ) throw(SQLException, RuntimeException) 479 { 480 ::osl::MutexGuard aGuard( m_aMutex ); 481 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed); 482 483 m_aLastWarning = SQLWarning(); 484 } 485 // ------------------------------------------------------------------------- 486 ::cppu::IPropertyArrayHelper* KabCommonStatement::createArrayHelper( ) const 487 { 488 // this properties are defined by the service statement 489 // they must be in alphabetic order 490 Sequence< Property > aProps(10); 491 Property* pProperties = aProps.getArray(); 492 sal_Int32 nPos = 0; 493 DECL_PROP0(CURSORNAME, ::rtl::OUString); 494 DECL_BOOL_PROP0(ESCAPEPROCESSING); 495 DECL_PROP0(FETCHDIRECTION,sal_Int32); 496 DECL_PROP0(FETCHSIZE, sal_Int32); 497 DECL_PROP0(MAXFIELDSIZE,sal_Int32); 498 DECL_PROP0(MAXROWS, sal_Int32); 499 DECL_PROP0(QUERYTIMEOUT,sal_Int32); 500 DECL_PROP0(RESULTSETCONCURRENCY,sal_Int32); 501 DECL_PROP0(RESULTSETTYPE,sal_Int32); 502 DECL_BOOL_PROP0(USEBOOKMARKS); 503 504 return new ::cppu::OPropertyArrayHelper(aProps); 505 } 506 // ------------------------------------------------------------------------- 507 ::cppu::IPropertyArrayHelper & KabCommonStatement::getInfoHelper() 508 { 509 return *const_cast<KabCommonStatement*>(this)->getArrayHelper(); 510 } 511 // ------------------------------------------------------------------------- 512 sal_Bool KabCommonStatement::convertFastPropertyValue( 513 Any &, 514 Any &, 515 sal_Int32, 516 const Any&) throw (::com::sun::star::lang::IllegalArgumentException) 517 { 518 sal_Bool bConverted = sal_False; 519 // here we have to try to convert 520 return bConverted; 521 } 522 // ------------------------------------------------------------------------- 523 void KabCommonStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any&) throw (Exception) 524 { 525 // set the value to whatever is nescessary 526 switch (nHandle) 527 { 528 case PROPERTY_ID_QUERYTIMEOUT: 529 case PROPERTY_ID_MAXFIELDSIZE: 530 case PROPERTY_ID_MAXROWS: 531 case PROPERTY_ID_CURSORNAME: 532 case PROPERTY_ID_RESULTSETCONCURRENCY: 533 case PROPERTY_ID_RESULTSETTYPE: 534 case PROPERTY_ID_FETCHDIRECTION: 535 case PROPERTY_ID_FETCHSIZE: 536 case PROPERTY_ID_ESCAPEPROCESSING: 537 case PROPERTY_ID_USEBOOKMARKS: 538 default: 539 ; 540 } 541 } 542 // ------------------------------------------------------------------------- 543 void KabCommonStatement::getFastPropertyValue(Any&,sal_Int32 nHandle) const 544 { 545 switch (nHandle) 546 { 547 case PROPERTY_ID_QUERYTIMEOUT: 548 case PROPERTY_ID_MAXFIELDSIZE: 549 case PROPERTY_ID_MAXROWS: 550 case PROPERTY_ID_CURSORNAME: 551 case PROPERTY_ID_RESULTSETCONCURRENCY: 552 case PROPERTY_ID_RESULTSETTYPE: 553 case PROPERTY_ID_FETCHDIRECTION: 554 case PROPERTY_ID_FETCHSIZE: 555 case PROPERTY_ID_ESCAPEPROCESSING: 556 case PROPERTY_ID_USEBOOKMARKS: 557 default: 558 ; 559 } 560 } 561 // ----------------------------------------------------------------------------- 562 void SAL_CALL KabCommonStatement::acquire() throw() 563 { 564 KabCommonStatement_BASE::acquire(); 565 } 566 // ----------------------------------------------------------------------------- 567 void SAL_CALL KabCommonStatement::release() throw() 568 { 569 KabCommonStatement_BASE::release(); 570 } 571 // ----------------------------------------------------------------------------- 572 Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL KabCommonStatement::getPropertySetInfo( ) throw(RuntimeException) 573 { 574 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); 575 } 576 // ----------------------------------------------------------------------------- 577 KabStatement::KabStatement(KabConnection* _pConnection) 578 : KabStatement_BASE(_pConnection) 579 { 580 } 581