merge the formfield patch from ooo-build
[ooovba.git] / connectivity / source / drivers / macab / MacabStatement.cxx
blob29c8477234078f2d49ea73c0401d0a34394a9342
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: MacabStatement.cxx,v $
10 * $Revision: 1.3.56.3 $
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 "MacabStatement.hxx"
35 #include "MacabConnection.hxx"
36 #include "MacabAddressBook.hxx"
37 #include "MacabDriver.hxx"
38 #include "MacabResultSet.hxx"
39 #include "MacabResultSetMetaData.hxx"
40 #include "macabcondition.hxx"
41 #include "macaborder.hxx"
42 #include "TConnection.hxx"
43 #include <connectivity/dbexception.hxx>
44 #include "resource/sharedresources.hxx"
45 #include "resource/macab_res.hrc"
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::macab;
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 connectivity
65 namespace macab
67 void impl_throwError(sal_uInt16 _nErrorId)
69 ::connectivity::SharedResources aResources;
70 const ::rtl::OUString sError( aResources.getResourceString(_nErrorId) );
71 ::dbtools::throwGenericSQLException(sError,NULL);
76 IMPLEMENT_SERVICE_INFO(MacabStatement, "com.sun.star.sdbc.drivers.MacabStatement", "com.sun.star.sdbc.Statement");
77 //------------------------------------------------------------------------------
78 MacabCommonStatement::MacabCommonStatement(MacabConnection* _pConnection )
79 : MacabCommonStatement_BASE(m_aMutex),
80 OPropertySetHelper(MacabCommonStatement_BASE::rBHelper),
81 m_aParser(_pConnection->getDriver()->getMSFactory()),
82 m_aSQLIterator(_pConnection, _pConnection->createCatalog()->getTables(), m_aParser, NULL ),
83 m_pParseTree(NULL),
84 m_pConnection(_pConnection),
85 rBHelper(MacabCommonStatement_BASE::rBHelper)
87 m_pConnection->acquire();
89 // -----------------------------------------------------------------------------
90 MacabCommonStatement::~MacabCommonStatement()
93 // -----------------------------------------------------------------------------
94 void MacabCommonStatement::disposing()
96 MacabCommonStatement_BASE::disposing();
98 // -----------------------------------------------------------------------------
99 void MacabCommonStatement::resetParameters() const throw(::com::sun::star::sdbc::SQLException)
101 impl_throwError(STR_PARA_ONLY_PREPARED);
103 // -----------------------------------------------------------------------------
104 void MacabCommonStatement::getNextParameter(::rtl::OUString &) const throw(::com::sun::star::sdbc::SQLException)
106 impl_throwError(STR_PARA_ONLY_PREPARED);
108 // -----------------------------------------------------------------------------
109 MacabCondition *MacabCommonStatement::analyseWhereClause(const OSQLParseNode *pParseNode) const throw(SQLException)
111 if (pParseNode->count() == 3)
113 const OSQLParseNode *pLeft = pParseNode->getChild(0),
114 *pMiddle = pParseNode->getChild(1),
115 *pRight = pParseNode->getChild(2);
117 // WHERE ( ... ) ?
118 if (SQL_ISPUNCTUATION(pLeft, "(") && SQL_ISPUNCTUATION(pRight, ")"))
120 return analyseWhereClause(pMiddle);
122 else if (SQL_ISRULE(pParseNode, comparison_predicate))
124 if (pLeft->isToken() && pRight->isToken())
126 switch (pMiddle->getNodeType())
128 case SQL_NODE_EQUAL:
129 // WHERE 0 = 1
130 return new MacabConditionConstant(pLeft->getTokenValue() == pRight->getTokenValue());
132 case SQL_NODE_NOTEQUAL:
133 // WHERE 0 <> 1
134 // (might not be correct SQL... don't care, handling anyway)
135 return new MacabConditionConstant(pLeft->getTokenValue() != pRight->getTokenValue());
137 default:
138 break;
141 else if (SQL_ISRULE(pLeft, column_ref))
143 ::rtl::OUString sColumnName,
144 sTableRange;
146 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange);
148 if (pRight->isToken() || SQL_ISRULE(pRight, parameter))
150 ::rtl::OUString sMatchString;
152 if (pRight->isToken()) // WHERE Name = 'Doe'
153 sMatchString = pRight->getTokenValue();
154 else if (SQL_ISRULE(pRight, parameter)) // WHERE Name = ?
155 getNextParameter(sMatchString);
157 switch (pMiddle->getNodeType())
159 case SQL_NODE_EQUAL:
160 // WHERE Name = 'Smith'
161 return new MacabConditionEqual(m_pHeader, sColumnName, sMatchString);
163 case SQL_NODE_NOTEQUAL:
164 // WHERE Name <> 'Jones'
165 return new MacabConditionDifferent(m_pHeader, sColumnName, sMatchString);
167 default:
168 break;
173 else if (SQL_ISRULE(pParseNode, search_condition))
175 if (SQL_ISTOKEN(pMiddle, OR))
177 // WHERE Name = 'Smith' OR Name = 'Jones'
178 return new MacabConditionOr(
179 analyseWhereClause(pLeft),
180 analyseWhereClause(pRight));
183 else if (SQL_ISRULE(pParseNode, boolean_term))
185 if (SQL_ISTOKEN(pMiddle, AND))
187 // WHERE Name = 'Smith' AND "Given Name" = 'Peter'
188 return new MacabConditionAnd(
189 analyseWhereClause(pLeft),
190 analyseWhereClause(pRight));
194 else if (pParseNode->count() == 4)
196 const OSQLParseNode *pLeft = pParseNode->getChild(0),
197 *pMiddleLeft = pParseNode->getChild(1),
198 *pMiddleRight = pParseNode->getChild(2),
199 *pRight = pParseNode->getChild(3);
201 if (SQL_ISRULE(pParseNode, test_for_null))
203 if (SQL_ISRULE(pLeft, column_ref) &&
204 SQL_ISTOKEN(pMiddleLeft, IS) &&
205 SQL_ISTOKEN(pRight, NULL))
207 ::rtl::OUString sColumnName,
208 sTableRange;
210 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange);
212 if (SQL_ISTOKEN(pMiddleRight, NOT))
214 // WHERE "Mobile Phone" IS NOT NULL
215 return new MacabConditionNotNull(m_pHeader, sColumnName);
217 else
219 // WHERE "Mobile Phone" IS NULL
220 return new MacabConditionNull(m_pHeader, sColumnName);
224 else if (SQL_ISRULE(pParseNode, like_predicate))
226 if (SQL_ISRULE(pLeft, column_ref))
228 ::rtl::OUString sColumnName,
229 sTableRange;
231 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange);
233 if (pMiddleRight->isToken() || SQL_ISRULE(pMiddleRight, parameter))
235 ::rtl::OUString sMatchString;
237 if (pMiddleRight->isToken()) // WHERE Name LIKE 'Sm%'
238 sMatchString = pMiddleRight->getTokenValue();
239 else if (SQL_ISRULE(pMiddleRight, parameter)) // WHERE Name LIKE ?
240 getNextParameter(sMatchString);
242 return new MacabConditionSimilar(m_pHeader, sColumnName, sMatchString);
247 impl_throwError(STR_QUERY_TOO_COMPLEX);
248 // Unreachable:
249 OSL_ASSERT(false);
250 return 0;
252 // -----------------------------------------------------------------------------
253 MacabOrder *MacabCommonStatement::analyseOrderByClause(const OSQLParseNode *pParseNode) const throw(SQLException)
255 if (SQL_ISRULE(pParseNode, ordering_spec_commalist))
257 MacabComplexOrder *list = new MacabComplexOrder();
258 sal_uInt32 n = pParseNode->count();
260 // Iterate through the ordering columns
261 for (sal_uInt32 i = 0; i < n; i++)
263 list->addOrder
264 (analyseOrderByClause(pParseNode->getChild(i)));
267 return list;
269 else if (SQL_ISRULE(pParseNode, ordering_spec))
271 if (pParseNode->count() == 2)
273 OSQLParseNode* pColumnRef = pParseNode->getChild(0);
274 OSQLParseNode* pAscendingDescending = pParseNode->getChild(1);
276 if (SQL_ISRULE(pColumnRef, column_ref))
278 if (pColumnRef->count() == 3)
279 pColumnRef = pColumnRef->getChild(2);
281 if (pColumnRef->count() == 1)
283 ::rtl::OUString sColumnName =
284 pColumnRef->getChild(0)->getTokenValue();
285 sal_Bool bAscending =
286 SQL_ISTOKEN(pAscendingDescending, DESC)?
287 sal_False:
288 sal_True;
290 return new MacabSimpleOrder(m_pHeader, sColumnName, bAscending);
295 impl_throwError(STR_QUERY_TOO_COMPLEX);
296 // Unreachable:
297 OSL_ASSERT(false);
298 return 0;
300 //------------------------------------------------------------------------------
301 ::rtl::OUString MacabCommonStatement::getTableName() const
303 const OSQLTables& xTabs = m_aSQLIterator.getTables();
305 if( xTabs.empty() )
306 return ::rtl::OUString();
308 // can only deal with one table at a time
309 if(xTabs.size() > 1 || m_aSQLIterator.hasErrors() )
310 return ::rtl::OUString();
312 return xTabs.begin()->first;
314 //------------------------------------------------------------------------------
315 void MacabCommonStatement::setMacabFields(MacabResultSet *pResult) const throw(SQLException)
317 ::vos::ORef<connectivity::OSQLColumns> xColumns; // selected columns
318 MacabResultSetMetaData *pMeta; // meta information - holds the list of AddressBook fields
320 xColumns = m_aSQLIterator.getSelectColumns();
321 if (!xColumns.isValid())
323 ::connectivity::SharedResources aResources;
324 const ::rtl::OUString sError( aResources.getResourceString(
325 STR_INVALID_COLUMN_SELECTION
326 ) );
327 ::dbtools::throwGenericSQLException(sError,NULL);
329 pMeta = static_cast<MacabResultSetMetaData *>(pResult->getMetaData().get());
330 pMeta->setMacabFields(xColumns);
332 // -------------------------------------------------------------------------
333 void MacabCommonStatement::selectRecords(MacabResultSet *pResult) const throw(SQLException)
335 const OSQLParseNode *pParseNode;
336 MacabCondition *pCondition;
338 pParseNode = m_aSQLIterator.getWhereTree();
339 if (pParseNode != NULL)
341 if (SQL_ISRULE(pParseNode, where_clause))
343 // Since we don't support parameters, don't reset them. If we ever
344 // support them, uncomment this line and fix resetParameters.
345 //resetParameters();
346 pParseNode = pParseNode->getChild(1);
347 pCondition = analyseWhereClause(pParseNode);
348 if (pCondition->isAlwaysTrue())
349 pResult->allMacabRecords();
350 else if (!pCondition->isAlwaysFalse())
351 pResult->someMacabRecords(pCondition);
352 delete pCondition;
353 return;
357 // no WHERE clause: get all rows
358 pResult->allMacabRecords();
360 // -------------------------------------------------------------------------
361 void MacabCommonStatement::sortRecords(MacabResultSet *pResult) const throw(SQLException)
363 const OSQLParseNode *pParseNode;
364 MacabOrder *pOrder;
366 pParseNode = m_aSQLIterator.getOrderTree();
367 if (pParseNode != NULL)
369 if (SQL_ISRULE(pParseNode, opt_order_by_clause))
371 pParseNode = pParseNode->getChild(2);
372 pOrder = analyseOrderByClause(pParseNode);
373 pResult->sortMacabRecords(pOrder);
374 delete pOrder;
378 //-----------------------------------------------------------------------------
379 Any SAL_CALL MacabCommonStatement::queryInterface( const Type & rType ) throw(RuntimeException)
381 Any aRet = MacabCommonStatement_BASE::queryInterface(rType);
382 if (!aRet.hasValue())
383 aRet = OPropertySetHelper::queryInterface(rType);
384 return aRet;
386 // -------------------------------------------------------------------------
387 Sequence< Type > SAL_CALL MacabCommonStatement::getTypes( ) throw(RuntimeException)
389 ::cppu::OTypeCollection aTypes( ::getCppuType( (const Reference< XMultiPropertySet > *)0 ),
390 ::getCppuType( (const Reference< XFastPropertySet > *)0 ),
391 ::getCppuType( (const Reference< XPropertySet > *)0 ));
393 return comphelper::concatSequences(aTypes.getTypes(),MacabCommonStatement_BASE::getTypes());
395 // -------------------------------------------------------------------------
396 void SAL_CALL MacabCommonStatement::cancel( ) throw(RuntimeException)
398 ::osl::MutexGuard aGuard( m_aMutex );
400 checkDisposed(MacabCommonStatement_BASE::rBHelper.bDisposed);
401 // cancel the current sql statement
403 // -------------------------------------------------------------------------
404 void SAL_CALL MacabCommonStatement::close( ) throw(SQLException, RuntimeException)
407 ::osl::MutexGuard aGuard( m_aMutex );
408 checkDisposed(MacabCommonStatement_BASE::rBHelper.bDisposed);
411 dispose();
413 // -------------------------------------------------------------------------
414 sal_Bool SAL_CALL MacabCommonStatement::execute(
415 const ::rtl::OUString& sql ) throw(SQLException, RuntimeException)
417 ::osl::MutexGuard aGuard( m_aMutex );
418 checkDisposed(MacabCommonStatement_BASE::rBHelper.bDisposed);
420 Reference< XResultSet > xRS = executeQuery(sql);
422 return xRS.is();
424 // -------------------------------------------------------------------------
425 Reference< XResultSet > SAL_CALL MacabCommonStatement::executeQuery(
426 const ::rtl::OUString& sql ) throw(SQLException, RuntimeException)
428 ::osl::MutexGuard aGuard( m_aMutex );
429 checkDisposed(MacabCommonStatement_BASE::rBHelper.bDisposed);
431 OSL_TRACE("Mac OS Address book - SQL Request: %s", OUtoCStr(sql));
433 MacabResultSet* pResult = new MacabResultSet(this);
434 Reference< XResultSet > xRS = pResult;
435 ::rtl::OUString aErr;
437 m_pParseTree = m_aParser.parseTree(aErr, sql);
438 if (m_pParseTree == NULL)
439 throw SQLException(aErr, *this, aErr, 0, Any());
441 m_aSQLIterator.setParseTree(m_pParseTree);
442 m_aSQLIterator.traverseAll();
443 switch (m_aSQLIterator.getStatementType())
445 case SQL_STATEMENT_SELECT:
447 ::rtl::OUString sTableName = getTableName(); // FROM which table ?
448 if (sTableName.getLength() != 0) // a match
450 MacabRecords *aRecords;
451 aRecords = m_pConnection->getAddressBook()->getMacabRecords(sTableName);
453 // In case, somehow, we don't have anything with the name m_sTableName
454 if(aRecords == NULL)
456 impl_throwError(STR_NO_TABLE);
458 else
460 m_pHeader = aRecords->getHeader();
462 pResult->setTableName(sTableName);
464 setMacabFields(pResult); // SELECT which columns ?
465 selectRecords(pResult); // WHERE which condition ?
466 sortRecords(pResult); // ORDER BY which columns ?
468 // To be continued: DISTINCT
469 // etc...
472 break;
474 default:
475 // To be continued: UPDATE
476 // DELETE
477 // etc...
478 impl_throwError(STR_QUERY_TOO_COMPLEX);
481 m_xResultSet = Reference<XResultSet>(pResult);
482 return xRS;
484 // -------------------------------------------------------------------------
485 Reference< XConnection > SAL_CALL MacabCommonStatement::getConnection( ) throw(SQLException, RuntimeException)
487 ::osl::MutexGuard aGuard( m_aMutex );
488 checkDisposed(MacabCommonStatement_BASE::rBHelper.bDisposed);
490 // just return our connection here
491 return (Reference< XConnection >) m_pConnection;
493 // -------------------------------------------------------------------------
494 sal_Int32 SAL_CALL MacabCommonStatement::executeUpdate( const ::rtl::OUString& ) throw(SQLException, RuntimeException)
496 ::osl::MutexGuard aGuard( m_aMutex );
497 checkDisposed(MacabCommonStatement_BASE::rBHelper.bDisposed);
499 // the return values gives information about how many rows are affected by executing the sql statement
500 return 0;
502 // -------------------------------------------------------------------------
503 Any SAL_CALL MacabCommonStatement::getWarnings( ) throw(SQLException, RuntimeException)
505 ::osl::MutexGuard aGuard( m_aMutex );
506 checkDisposed(MacabCommonStatement_BASE::rBHelper.bDisposed);
508 return makeAny(m_aLastWarning);
510 // -------------------------------------------------------------------------
511 void SAL_CALL MacabCommonStatement::clearWarnings( ) throw(SQLException, RuntimeException)
513 ::osl::MutexGuard aGuard( m_aMutex );
514 checkDisposed(MacabCommonStatement_BASE::rBHelper.bDisposed);
516 m_aLastWarning = SQLWarning();
518 // -------------------------------------------------------------------------
519 ::cppu::IPropertyArrayHelper* MacabCommonStatement::createArrayHelper( ) const
521 // this properties are defined by the service statement
522 // they must be in alphabetic order
523 Sequence< Property > aProps(10);
524 Property* pProperties = aProps.getArray();
525 sal_Int32 nPos = 0;
526 DECL_PROP0(CURSORNAME, ::rtl::OUString);
527 DECL_BOOL_PROP0(ESCAPEPROCESSING);
528 DECL_PROP0(FETCHDIRECTION,sal_Int32);
529 DECL_PROP0(FETCHSIZE, sal_Int32);
530 DECL_PROP0(MAXFIELDSIZE,sal_Int32);
531 DECL_PROP0(MAXROWS, sal_Int32);
532 DECL_PROP0(QUERYTIMEOUT,sal_Int32);
533 DECL_PROP0(RESULTSETCONCURRENCY,sal_Int32);
534 DECL_PROP0(RESULTSETTYPE,sal_Int32);
535 DECL_BOOL_PROP0(USEBOOKMARKS);
537 return new ::cppu::OPropertyArrayHelper(aProps);
539 // -------------------------------------------------------------------------
540 ::cppu::IPropertyArrayHelper & MacabCommonStatement::getInfoHelper()
542 return *const_cast<MacabCommonStatement*>(this)->getArrayHelper();
544 // -------------------------------------------------------------------------
545 sal_Bool MacabCommonStatement::convertFastPropertyValue(
546 Any &,
547 Any &,
548 sal_Int32,
549 const Any&) throw (::com::sun::star::lang::IllegalArgumentException)
551 sal_Bool bConverted = sal_False;
552 // here we have to try to convert
553 return bConverted;
555 // -------------------------------------------------------------------------
556 void MacabCommonStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any&) throw (Exception)
558 // set the value to whatever is nescessary
559 switch (nHandle)
561 case PROPERTY_ID_QUERYTIMEOUT:
562 case PROPERTY_ID_MAXFIELDSIZE:
563 case PROPERTY_ID_MAXROWS:
564 case PROPERTY_ID_CURSORNAME:
565 case PROPERTY_ID_RESULTSETCONCURRENCY:
566 case PROPERTY_ID_RESULTSETTYPE:
567 case PROPERTY_ID_FETCHDIRECTION:
568 case PROPERTY_ID_FETCHSIZE:
569 case PROPERTY_ID_ESCAPEPROCESSING:
570 case PROPERTY_ID_USEBOOKMARKS:
571 default:
575 // -------------------------------------------------------------------------
576 void MacabCommonStatement::getFastPropertyValue(Any&,sal_Int32 nHandle) const
578 switch (nHandle)
580 case PROPERTY_ID_QUERYTIMEOUT:
581 case PROPERTY_ID_MAXFIELDSIZE:
582 case PROPERTY_ID_MAXROWS:
583 case PROPERTY_ID_CURSORNAME:
584 case PROPERTY_ID_RESULTSETCONCURRENCY:
585 case PROPERTY_ID_RESULTSETTYPE:
586 case PROPERTY_ID_FETCHDIRECTION:
587 case PROPERTY_ID_FETCHSIZE:
588 case PROPERTY_ID_ESCAPEPROCESSING:
589 case PROPERTY_ID_USEBOOKMARKS:
590 default:
594 // -----------------------------------------------------------------------------
595 void SAL_CALL MacabCommonStatement::acquire() throw()
597 MacabCommonStatement_BASE::acquire();
599 // -----------------------------------------------------------------------------
600 void SAL_CALL MacabCommonStatement::release() throw()
602 MacabCommonStatement_BASE::release();
604 // -----------------------------------------------------------------------------
605 Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL MacabCommonStatement::getPropertySetInfo( ) throw(RuntimeException)
607 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
609 // -----------------------------------------------------------------------------
610 MacabStatement::MacabStatement(MacabConnection* _pConnection)
611 : MacabStatement_BASE(_pConnection)