merge the formfield patch from ooo-build
[ooovba.git] / connectivity / source / drivers / kab / KStatement.cxx
blobd612b77976bfe71395e03fd6bedda71ddf29083c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: KStatement.cxx,v $
10 * $Revision: 1.8.56.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
34 #include "KStatement.hxx"
35 #include "KConnection.hxx"
36 #include "KDriver.hxx"
37 #include "KResultSet.hxx"
38 #include "KResultSetMetaData.hxx"
39 #include "kcondition.hxx"
40 #include "korder.hxx"
41 #include "TConnection.hxx"
42 #include <connectivity/dbexception.hxx>
43 #include "resource/kab_res.hrc"
44 #include "resource/sharedresources.hxx"
47 #if OSL_DEBUG_LEVEL > 0
48 # define OUtoCStr( x ) ( ::rtl::OUStringToOString ( (x), RTL_TEXTENCODING_ASCII_US).getStr())
49 #else /* OSL_DEBUG_LEVEL */
50 # define OUtoCStr( x ) ("dummy")
51 #endif /* OSL_DEBUG_LEVEL */
53 using namespace connectivity::kab;
54 using namespace com::sun::star::uno;
55 using namespace com::sun::star::lang;
56 using namespace com::sun::star::beans;
57 using namespace com::sun::star::sdbc;
58 using namespace com::sun::star::sdbcx;
59 using namespace com::sun::star::container;
60 using namespace com::sun::star::io;
61 using namespace com::sun::star::util;
63 namespace
65 void lcl_throwError(sal_uInt16 _nErrorId)
67 ::connectivity::SharedResources aResources;
68 const ::rtl::OUString sError( aResources.getResourceString(_nErrorId) );
69 ::dbtools::throwGenericSQLException(sError,NULL);
73 IMPLEMENT_SERVICE_INFO(KabStatement, "com.sun.star.sdbc.drivers.KabStatement", "com.sun.star.sdbc.Statement");
74 //------------------------------------------------------------------------------
75 KabCommonStatement::KabCommonStatement(KabConnection* _pConnection )
76 : KabCommonStatement_BASE(m_aMutex),
77 OPropertySetHelper(KabCommonStatement_BASE::rBHelper),
78 m_aParser(_pConnection->getDriver()->getMSFactory()),
79 m_aSQLIterator(_pConnection, _pConnection->createCatalog()->getTables(), m_aParser, NULL ),
80 m_pParseTree(NULL),
81 m_pConnection(_pConnection),
82 rBHelper(KabCommonStatement_BASE::rBHelper)
84 m_pConnection->acquire();
86 // -----------------------------------------------------------------------------
87 KabCommonStatement::~KabCommonStatement()
90 // -----------------------------------------------------------------------------
91 void KabCommonStatement::disposing()
93 KabCommonStatement_BASE::disposing();
95 // -----------------------------------------------------------------------------
96 void KabCommonStatement::resetParameters() const throw(::com::sun::star::sdbc::SQLException)
98 lcl_throwError(STR_PARA_ONLY_PREPARED);
100 // -----------------------------------------------------------------------------
101 void KabCommonStatement::getNextParameter(::rtl::OUString &) const throw(::com::sun::star::sdbc::SQLException)
103 lcl_throwError(STR_PARA_ONLY_PREPARED);
105 // -----------------------------------------------------------------------------
106 KabCondition *KabCommonStatement::analyseWhereClause(const OSQLParseNode *pParseNode) const throw(SQLException)
108 if (pParseNode->count() == 3)
110 const OSQLParseNode *pLeft = pParseNode->getChild(0),
111 *pMiddle = pParseNode->getChild(1),
112 *pRight = pParseNode->getChild(2);
114 // WHERE ( ... ) ?
115 if (SQL_ISPUNCTUATION(pLeft, "(") && SQL_ISPUNCTUATION(pRight, ")"))
117 return analyseWhereClause(pMiddle);
119 else if (SQL_ISRULE(pParseNode, comparison_predicate))
121 if (pLeft->isToken() && pRight->isToken())
123 switch (pMiddle->getNodeType())
125 case SQL_NODE_EQUAL:
126 // WHERE 0 = 1
127 return new KabConditionConstant(pLeft->getTokenValue() == pRight->getTokenValue());
129 case SQL_NODE_NOTEQUAL:
130 // WHERE 0 <> 1
131 // (might not be correct SQL... don't care, handling anyway)
132 return new KabConditionConstant(pLeft->getTokenValue() != pRight->getTokenValue());
134 default:
135 break;
138 else if (SQL_ISRULE(pLeft, column_ref))
140 ::rtl::OUString sColumnName,
141 sTableRange;
143 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange);
145 if (pRight->isToken() || SQL_ISRULE(pRight, parameter))
147 ::rtl::OUString sMatchString;
149 if (pRight->isToken()) // WHERE Name = 'Doe'
150 sMatchString = pRight->getTokenValue();
151 else if (SQL_ISRULE(pRight, parameter)) // WHERE Name = ?
152 getNextParameter(sMatchString);
154 switch (pMiddle->getNodeType())
156 case SQL_NODE_EQUAL:
157 // WHERE Name = 'Smith'
158 return new KabConditionEqual(sColumnName, sMatchString);
160 case SQL_NODE_NOTEQUAL:
161 // WHERE Name <> 'Jones'
162 return new KabConditionDifferent(sColumnName, sMatchString);
164 default:
165 break;
170 else if (SQL_ISRULE(pParseNode, search_condition))
172 if (SQL_ISTOKEN(pMiddle, OR))
174 // WHERE Name = 'Smith' OR Name = 'Jones'
175 return new KabConditionOr(
176 analyseWhereClause(pLeft),
177 analyseWhereClause(pRight));
180 else if (SQL_ISRULE(pParseNode, boolean_term))
182 if (SQL_ISTOKEN(pMiddle, AND))
184 // WHERE Name = 'Smith' AND "Given Name" = 'Peter'
185 return new KabConditionAnd(
186 analyseWhereClause(pLeft),
187 analyseWhereClause(pRight));
191 else if (pParseNode->count() == 4)
193 const OSQLParseNode *pLeft = pParseNode->getChild(0),
194 *pMiddleLeft = pParseNode->getChild(1),
195 *pMiddleRight = pParseNode->getChild(2),
196 *pRight = pParseNode->getChild(3);
198 if (SQL_ISRULE(pParseNode, test_for_null))
200 if (SQL_ISRULE(pLeft, column_ref) &&
201 SQL_ISTOKEN(pMiddleLeft, IS) &&
202 SQL_ISTOKEN(pRight, NULL))
204 ::rtl::OUString sColumnName,
205 sTableRange;
207 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange);
209 if (SQL_ISTOKEN(pMiddleRight, NOT))
211 // WHERE "Mobile Phone" IS NOT NULL
212 return new KabConditionNotNull(sColumnName);
214 else
216 // WHERE "Mobile Phone" IS NULL
217 return new KabConditionNull(sColumnName);
221 else if (SQL_ISRULE(pParseNode, like_predicate))
223 if (SQL_ISRULE(pLeft, column_ref))
225 ::rtl::OUString sColumnName,
226 sTableRange;
228 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange);
230 if (pMiddleRight->isToken() || SQL_ISRULE(pMiddleRight, parameter))
232 ::rtl::OUString sMatchString;
234 if (pMiddleRight->isToken()) // WHERE Name LIKE 'Sm%'
235 sMatchString = pMiddleRight->getTokenValue();
236 else if (SQL_ISRULE(pMiddleRight, parameter)) // WHERE Name LIKE ?
237 getNextParameter(sMatchString);
239 return new KabConditionSimilar(sColumnName, sMatchString);
245 lcl_throwError(STR_QUERY_TOO_COMPLEX);
247 // Unreachable:
248 OSL_ASSERT(false);
249 return 0;
251 // -----------------------------------------------------------------------------
252 KabOrder *KabCommonStatement::analyseOrderByClause(const OSQLParseNode *pParseNode) const throw(SQLException)
254 if (SQL_ISRULE(pParseNode, ordering_spec_commalist))
256 KabComplexOrder *list = new KabComplexOrder();
257 sal_uInt32 n = pParseNode->count();
259 // Iterate through the ordering columns
260 for (sal_uInt32 i = 0; i < n; i++)
262 list->addOrder
263 (analyseOrderByClause(pParseNode->getChild(i)));
266 return list;
268 else if (SQL_ISRULE(pParseNode, ordering_spec))
270 if (pParseNode->count() == 2)
272 OSQLParseNode* pColumnRef = pParseNode->getChild(0);
273 OSQLParseNode* pAscendingDescending = pParseNode->getChild(1);
275 if (SQL_ISRULE(pColumnRef, column_ref))
277 if (pColumnRef->count() == 3)
278 pColumnRef = pColumnRef->getChild(2);
280 if (pColumnRef->count() == 1)
282 ::rtl::OUString sColumnName =
283 pColumnRef->getChild(0)->getTokenValue();
284 sal_Bool bAscending =
285 SQL_ISTOKEN(pAscendingDescending, DESC)?
286 sal_False:
287 sal_True;
289 return new KabSimpleOrder(sColumnName, bAscending);
294 lcl_throwError(STR_QUERY_TOO_COMPLEX);
295 // Unreachable:
296 OSL_ASSERT(false);
297 return 0;
299 //------------------------------------------------------------------------------
300 sal_Bool KabCommonStatement::isTableKnown(KabResultSet *pResult) const
302 // can handle requests like SELECT * FROM addresses addresses
303 // but cannot handle requests like SELECT * FROM addresses persons
304 if (m_aSQLIterator.getTables().size() != 1)
305 return sal_False;
307 if (m_aSQLIterator.getTables().begin()->first != pResult->getMetaData()->getTableName(0))
308 return sal_False;
310 return sal_True;
312 //------------------------------------------------------------------------------
313 void KabCommonStatement::setKabFields(KabResultSet *pResult) const throw(SQLException)
315 ::vos::ORef<connectivity::OSQLColumns> xColumns; // selected columns
316 KabResultSetMetaData *pMeta; // meta information - holds the list of KAddressBook fields
318 xColumns = m_aSQLIterator.getSelectColumns();
319 if (!xColumns.isValid())
321 lcl_throwError(STR_INVALID_COLUMN_SELECTION);
323 pMeta = static_cast<KabResultSetMetaData *>(pResult->getMetaData().get());
324 pMeta->setKabFields(xColumns);
326 // -------------------------------------------------------------------------
327 void KabCommonStatement::selectAddressees(KabResultSet *pResult) const throw(SQLException)
329 const OSQLParseNode *pParseNode;
330 KabCondition *pCondition;
332 pParseNode = m_aSQLIterator.getWhereTree();
333 if (pParseNode != NULL)
335 if (SQL_ISRULE(pParseNode, where_clause))
337 resetParameters();
338 pParseNode = pParseNode->getChild(1);
339 pCondition = analyseWhereClause(pParseNode);
340 if (pCondition->isAlwaysTrue())
341 pResult->allKabAddressees();
342 else if (!pCondition->isAlwaysFalse())
343 pResult->someKabAddressees(pCondition);
344 delete pCondition;
345 return;
349 // no WHERE clause: get all rows
350 pResult->allKabAddressees();
352 // -------------------------------------------------------------------------
353 void KabCommonStatement::sortAddressees(KabResultSet *pResult) const throw(SQLException)
355 const OSQLParseNode *pParseNode;
356 KabOrder *pOrder;
358 pParseNode = m_aSQLIterator.getOrderTree();
359 if (pParseNode != NULL)
361 if (SQL_ISRULE(pParseNode, opt_order_by_clause))
363 pParseNode = pParseNode->getChild(2);
364 pOrder = analyseOrderByClause(pParseNode);
365 pResult->sortKabAddressees(pOrder);
366 delete pOrder;
370 //-----------------------------------------------------------------------------
371 Any SAL_CALL KabCommonStatement::queryInterface( const Type & rType ) throw(RuntimeException)
373 Any aRet = KabCommonStatement_BASE::queryInterface(rType);
374 if (!aRet.hasValue())
375 aRet = OPropertySetHelper::queryInterface(rType);
376 return aRet;
378 // -------------------------------------------------------------------------
379 Sequence< Type > SAL_CALL KabCommonStatement::getTypes( ) throw(RuntimeException)
381 ::cppu::OTypeCollection aTypes( ::getCppuType( (const Reference< XMultiPropertySet > *)0 ),
382 ::getCppuType( (const Reference< XFastPropertySet > *)0 ),
383 ::getCppuType( (const Reference< XPropertySet > *)0 ));
385 return comphelper::concatSequences(aTypes.getTypes(),KabCommonStatement_BASE::getTypes());
387 // -------------------------------------------------------------------------
388 void SAL_CALL KabCommonStatement::cancel( ) throw(RuntimeException)
390 ::osl::MutexGuard aGuard( m_aMutex );
392 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
393 // cancel the current sql statement
395 // -------------------------------------------------------------------------
396 void SAL_CALL KabCommonStatement::close( ) throw(SQLException, RuntimeException)
399 ::osl::MutexGuard aGuard( m_aMutex );
400 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
403 dispose();
405 // -------------------------------------------------------------------------
406 sal_Bool SAL_CALL KabCommonStatement::execute(
407 const ::rtl::OUString& sql ) throw(SQLException, RuntimeException)
409 ::osl::MutexGuard aGuard( m_aMutex );
410 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
412 Reference< XResultSet > xRS = executeQuery(sql);
414 return xRS.is();
416 // -------------------------------------------------------------------------
417 Reference< XResultSet > SAL_CALL KabCommonStatement::executeQuery(
418 const ::rtl::OUString& sql ) throw(SQLException, RuntimeException)
420 ::osl::MutexGuard aGuard( m_aMutex );
421 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
423 OSL_TRACE("KDE Address book - SQL Request: %s", OUtoCStr(sql));
425 KabResultSet* pResult = new KabResultSet(this);
426 Reference< XResultSet > xRS = pResult;
427 ::rtl::OUString aErr;
429 m_pParseTree = m_aParser.parseTree(aErr, sql);
430 if (m_pParseTree == NULL)
431 throw SQLException(aErr, *this, aErr, 0, Any());
433 m_aSQLIterator.setParseTree(m_pParseTree);
434 m_aSQLIterator.traverseAll();
435 switch (m_aSQLIterator.getStatementType())
437 case SQL_STATEMENT_SELECT:
438 if (isTableKnown(pResult)) // FROM which table ?
440 setKabFields(pResult); // SELECT which columns ?
441 selectAddressees(pResult); // WHERE which condition ?
442 sortAddressees(pResult); // ORDER BY which columns ?
443 // To be continued: DISTINCT
444 // etc...
446 break;
448 default:
449 // To be continued: UPDATE
450 // DELETE
451 // etc...
452 lcl_throwError(STR_QUERY_TOO_COMPLEX);
455 return xRS;
457 // -------------------------------------------------------------------------
458 Reference< XConnection > SAL_CALL KabCommonStatement::getConnection( ) throw(SQLException, RuntimeException)
460 ::osl::MutexGuard aGuard( m_aMutex );
461 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
463 // just return our connection here
464 return (Reference< XConnection >) m_pConnection;
466 // -------------------------------------------------------------------------
467 sal_Int32 SAL_CALL KabCommonStatement::executeUpdate( const ::rtl::OUString& ) throw(SQLException, RuntimeException)
469 ::osl::MutexGuard aGuard( m_aMutex );
470 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
472 // the return values gives information about how many rows are affected by executing the sql statement
473 return 0;
475 // -------------------------------------------------------------------------
476 Any SAL_CALL KabCommonStatement::getWarnings( ) throw(SQLException, RuntimeException)
478 ::osl::MutexGuard aGuard( m_aMutex );
479 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
481 return makeAny(m_aLastWarning);
483 // -------------------------------------------------------------------------
484 void SAL_CALL KabCommonStatement::clearWarnings( ) throw(SQLException, RuntimeException)
486 ::osl::MutexGuard aGuard( m_aMutex );
487 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
489 m_aLastWarning = SQLWarning();
491 // -------------------------------------------------------------------------
492 ::cppu::IPropertyArrayHelper* KabCommonStatement::createArrayHelper( ) const
494 // this properties are defined by the service statement
495 // they must be in alphabetic order
496 Sequence< Property > aProps(10);
497 Property* pProperties = aProps.getArray();
498 sal_Int32 nPos = 0;
499 DECL_PROP0(CURSORNAME, ::rtl::OUString);
500 DECL_BOOL_PROP0(ESCAPEPROCESSING);
501 DECL_PROP0(FETCHDIRECTION,sal_Int32);
502 DECL_PROP0(FETCHSIZE, sal_Int32);
503 DECL_PROP0(MAXFIELDSIZE,sal_Int32);
504 DECL_PROP0(MAXROWS, sal_Int32);
505 DECL_PROP0(QUERYTIMEOUT,sal_Int32);
506 DECL_PROP0(RESULTSETCONCURRENCY,sal_Int32);
507 DECL_PROP0(RESULTSETTYPE,sal_Int32);
508 DECL_BOOL_PROP0(USEBOOKMARKS);
510 return new ::cppu::OPropertyArrayHelper(aProps);
512 // -------------------------------------------------------------------------
513 ::cppu::IPropertyArrayHelper & KabCommonStatement::getInfoHelper()
515 return *const_cast<KabCommonStatement*>(this)->getArrayHelper();
517 // -------------------------------------------------------------------------
518 sal_Bool KabCommonStatement::convertFastPropertyValue(
519 Any &,
520 Any &,
521 sal_Int32,
522 const Any&) throw (::com::sun::star::lang::IllegalArgumentException)
524 sal_Bool bConverted = sal_False;
525 // here we have to try to convert
526 return bConverted;
528 // -------------------------------------------------------------------------
529 void KabCommonStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any&) throw (Exception)
531 // set the value to whatever is nescessary
532 switch (nHandle)
534 case PROPERTY_ID_QUERYTIMEOUT:
535 case PROPERTY_ID_MAXFIELDSIZE:
536 case PROPERTY_ID_MAXROWS:
537 case PROPERTY_ID_CURSORNAME:
538 case PROPERTY_ID_RESULTSETCONCURRENCY:
539 case PROPERTY_ID_RESULTSETTYPE:
540 case PROPERTY_ID_FETCHDIRECTION:
541 case PROPERTY_ID_FETCHSIZE:
542 case PROPERTY_ID_ESCAPEPROCESSING:
543 case PROPERTY_ID_USEBOOKMARKS:
544 default:
548 // -------------------------------------------------------------------------
549 void KabCommonStatement::getFastPropertyValue(Any&,sal_Int32 nHandle) const
551 switch (nHandle)
553 case PROPERTY_ID_QUERYTIMEOUT:
554 case PROPERTY_ID_MAXFIELDSIZE:
555 case PROPERTY_ID_MAXROWS:
556 case PROPERTY_ID_CURSORNAME:
557 case PROPERTY_ID_RESULTSETCONCURRENCY:
558 case PROPERTY_ID_RESULTSETTYPE:
559 case PROPERTY_ID_FETCHDIRECTION:
560 case PROPERTY_ID_FETCHSIZE:
561 case PROPERTY_ID_ESCAPEPROCESSING:
562 case PROPERTY_ID_USEBOOKMARKS:
563 default:
567 // -----------------------------------------------------------------------------
568 void SAL_CALL KabCommonStatement::acquire() throw()
570 KabCommonStatement_BASE::acquire();
572 // -----------------------------------------------------------------------------
573 void SAL_CALL KabCommonStatement::release() throw()
575 KabCommonStatement_BASE::release();
577 // -----------------------------------------------------------------------------
578 Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL KabCommonStatement::getPropertySetInfo( ) throw(RuntimeException)
580 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
582 // -----------------------------------------------------------------------------
583 KabStatement::KabStatement(KabConnection* _pConnection)
584 : KabStatement_BASE(_pConnection)