update emoji autocorrect entries from po-files
[LibreOffice.git] / connectivity / source / drivers / kab / KStatement.cxx
blob5eab3b7a28a586a7bc9c3bdd9e570220016af116
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "KStatement.hxx"
22 #include "KConnection.hxx"
23 #include "KDriver.hxx"
24 #include "KResultSet.hxx"
25 #include "KResultSetMetaData.hxx"
26 #include "kcondition.hxx"
27 #include "korder.hxx"
28 #include "TConnection.hxx"
29 #include <connectivity/dbexception.hxx>
30 #include "resource/kab_res.hrc"
31 #include "resource/sharedresources.hxx"
32 #include "sqlbison.hxx"
35 #if OSL_DEBUG_LEVEL > 0
36 # define OUtoCStr( x ) ( OUStringToOString ( (x), RTL_TEXTENCODING_ASCII_US).getStr())
37 #else /* OSL_DEBUG_LEVEL */
38 # define OUtoCStr( x ) ("dummy")
39 #endif /* OSL_DEBUG_LEVEL */
41 using namespace connectivity::kab;
42 using namespace com::sun::star::uno;
43 using namespace com::sun::star::lang;
44 using namespace com::sun::star::beans;
45 using namespace com::sun::star::sdbc;
46 using namespace com::sun::star::sdbcx;
47 using namespace com::sun::star::container;
48 using namespace com::sun::star::io;
49 using namespace com::sun::star::util;
51 namespace
53 void lcl_throwError(sal_uInt16 _nErrorId)
55 ::connectivity::SharedResources aResources;
56 const OUString sError( aResources.getResourceString(_nErrorId) );
57 ::dbtools::throwGenericSQLException(sError,NULL);
61 IMPLEMENT_SERVICE_INFO(KabStatement, "com.sun.star.sdbc.drivers.KabStatement", "com.sun.star.sdbc.Statement");
63 KabCommonStatement::KabCommonStatement(KabConnection* _pConnection )
64 : KabCommonStatement_BASE(m_aMutex),
65 OPropertySetHelper(KabCommonStatement_BASE::rBHelper),
66 m_aParser(_pConnection->getComponentContext()),
67 m_aSQLIterator(_pConnection, _pConnection->createCatalog()->getTables(), m_aParser, NULL ),
68 m_pParseTree(NULL),
69 m_pConnection(_pConnection),
70 rBHelper(KabCommonStatement_BASE::rBHelper)
72 m_pConnection->acquire();
75 KabCommonStatement::~KabCommonStatement()
79 void KabCommonStatement::disposing()
81 KabCommonStatement_BASE::disposing();
84 void KabCommonStatement::resetParameters() const throw(::com::sun::star::sdbc::SQLException)
86 lcl_throwError(STR_PARA_ONLY_PREPARED);
89 void KabCommonStatement::getNextParameter(OUString &) const throw(::com::sun::star::sdbc::SQLException)
91 lcl_throwError(STR_PARA_ONLY_PREPARED);
94 KabCondition *KabCommonStatement::analyseWhereClause(const OSQLParseNode *pParseNode) const throw(SQLException)
96 if (pParseNode->count() == 3)
98 const OSQLParseNode *pLeft = pParseNode->getChild(0),
99 *pMiddle = pParseNode->getChild(1),
100 *pRight = pParseNode->getChild(2);
102 // WHERE ( ... ) ?
103 if (SQL_ISPUNCTUATION(pLeft, "(") && SQL_ISPUNCTUATION(pRight, ")"))
105 return analyseWhereClause(pMiddle);
107 else if (SQL_ISRULE(pParseNode, comparison_predicate))
109 if (pLeft->isToken() && pRight->isToken())
111 switch (pMiddle->getNodeType())
113 case SQL_NODE_EQUAL:
114 // WHERE 0 = 1
115 return new KabConditionConstant(pLeft->getTokenValue() == pRight->getTokenValue());
117 case SQL_NODE_NOTEQUAL:
118 // WHERE 0 <> 1
119 // (might not be correct SQL... don't care, handling anyway)
120 return new KabConditionConstant(pLeft->getTokenValue() != pRight->getTokenValue());
122 default:
123 break;
126 else if (SQL_ISRULE(pLeft, column_ref))
128 OUString sColumnName,
129 sTableRange;
131 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange);
133 if (pRight->isToken() || SQL_ISRULE(pRight, parameter))
135 OUString sMatchString;
137 if (pRight->isToken()) // WHERE Name = 'Doe'
138 sMatchString = pRight->getTokenValue();
139 else if (SQL_ISRULE(pRight, parameter)) // WHERE Name = ?
140 getNextParameter(sMatchString);
142 switch (pMiddle->getNodeType())
144 case SQL_NODE_EQUAL:
145 // WHERE Name = 'Smith'
146 return new KabConditionEqual(sColumnName, sMatchString);
148 case SQL_NODE_NOTEQUAL:
149 // WHERE Name <> 'Jones'
150 return new KabConditionDifferent(sColumnName, sMatchString);
152 default:
153 break;
158 else if (SQL_ISRULE(pParseNode, search_condition))
160 if (SQL_ISTOKEN(pMiddle, OR))
162 // WHERE Name = 'Smith' OR Name = 'Jones'
163 return new KabConditionOr(
164 analyseWhereClause(pLeft),
165 analyseWhereClause(pRight));
168 else if (SQL_ISRULE(pParseNode, boolean_term))
170 if (SQL_ISTOKEN(pMiddle, AND))
172 // WHERE Name = 'Smith' AND "Given Name" = 'Peter'
173 return new KabConditionAnd(
174 analyseWhereClause(pLeft),
175 analyseWhereClause(pRight));
179 else if (SQL_ISRULE(pParseNode, test_for_null) || SQL_ISRULE(pParseNode, like_predicate))
181 const OSQLParseNode *pLeft = pParseNode->getChild(0);
182 const OSQLParseNode* pPart2 = pParseNode->getChild(1);
183 const OSQLParseNode *pMiddleLeft = pPart2->getChild(0),
184 *pMiddleRight = pPart2->getChild(1),
185 *pRight = pPart2->getChild(2);
187 if (SQL_ISRULE(pParseNode, test_for_null))
189 if (SQL_ISRULE(pLeft, column_ref) &&
190 SQL_ISTOKEN(pMiddleLeft, IS) &&
191 SQL_ISTOKEN(pRight, NULL))
193 OUString sColumnName,
194 sTableRange;
196 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange);
198 if (SQL_ISTOKEN(pMiddleRight, NOT))
200 // WHERE "Mobile Phone" IS NOT NULL
201 return new KabConditionNotNull(sColumnName);
203 else
205 // WHERE "Mobile Phone" IS NULL
206 return new KabConditionNull(sColumnName);
210 else if (SQL_ISRULE(pParseNode, like_predicate))
212 if (SQL_ISRULE(pLeft, column_ref))
214 OUString sColumnName,
215 sTableRange;
217 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange);
219 if (pMiddleRight->isToken() || SQL_ISRULE(pMiddleRight, parameter))
221 OUString sMatchString;
223 if (pMiddleRight->isToken()) // WHERE Name LIKE 'Sm%'
224 sMatchString = pMiddleRight->getTokenValue();
225 else if (SQL_ISRULE(pMiddleRight, parameter)) // WHERE Name LIKE ?
226 getNextParameter(sMatchString);
228 return new KabConditionSimilar(sColumnName, sMatchString);
234 lcl_throwError(STR_QUERY_TOO_COMPLEX);
236 // Unreachable:
237 OSL_ASSERT(false);
238 return 0;
241 KabOrder *KabCommonStatement::analyseOrderByClause(const OSQLParseNode *pParseNode) const throw(SQLException)
243 if (SQL_ISRULE(pParseNode, ordering_spec_commalist))
245 KabComplexOrder *list = new KabComplexOrder();
246 sal_uInt32 n = pParseNode->count();
248 // Iterate through the ordering columns
249 for (sal_uInt32 i = 0; i < n; i++)
251 list->addOrder
252 (analyseOrderByClause(pParseNode->getChild(i)));
255 return list;
257 else if (SQL_ISRULE(pParseNode, ordering_spec))
259 if (pParseNode->count() == 2)
261 OSQLParseNode* pColumnRef = pParseNode->getChild(0);
262 OSQLParseNode* pAscendingDescending = pParseNode->getChild(1);
264 if (SQL_ISRULE(pColumnRef, column_ref))
266 if (pColumnRef->count() == 3)
267 pColumnRef = pColumnRef->getChild(2);
269 if (pColumnRef->count() == 1)
271 OUString sColumnName =
272 pColumnRef->getChild(0)->getTokenValue();
273 bool bAscending =
274 !SQL_ISTOKEN(pAscendingDescending, DESC);
276 return new KabSimpleOrder(sColumnName, bAscending);
281 lcl_throwError(STR_QUERY_TOO_COMPLEX);
282 // Unreachable:
283 OSL_ASSERT(false);
284 return 0;
287 bool KabCommonStatement::isTableKnown(KabResultSet *pResult) const
289 // can handle requests like SELECT * FROM addresses addresses
290 // but cannot handle requests like SELECT * FROM addresses persons
291 if (m_aSQLIterator.getTables().size() != 1)
292 return false;
294 if (m_aSQLIterator.getTables().begin()->first != pResult->getMetaData()->getTableName(0))
295 return false;
297 return true;
300 void KabCommonStatement::setKabFields(KabResultSet *pResult) const throw(SQLException)
302 ::rtl::Reference<connectivity::OSQLColumns> xColumns; // selected columns
304 xColumns = m_aSQLIterator.getSelectColumns();
305 if (!xColumns.is())
307 lcl_throwError(STR_INVALID_COLUMN_SELECTION);
309 pResult->getKabMetaData()->setKabFields(xColumns);
312 void KabCommonStatement::selectAddressees(KabResultSet *pResult) const throw(SQLException)
314 const OSQLParseNode *pParseNode;
316 pParseNode = m_aSQLIterator.getWhereTree();
317 if (pParseNode != NULL)
319 if (SQL_ISRULE(pParseNode, where_clause))
321 resetParameters();
322 pParseNode = pParseNode->getChild(1);
323 KabCondition *pCondition = analyseWhereClause(pParseNode);
324 if (pCondition->isAlwaysTrue())
325 pResult->allKabAddressees();
326 else if (!pCondition->isAlwaysFalse())
327 pResult->someKabAddressees(pCondition);
328 delete pCondition;
329 return;
333 // no WHERE clause: get all rows
334 pResult->allKabAddressees();
337 void KabCommonStatement::sortAddressees(KabResultSet *pResult) const throw(SQLException)
339 const OSQLParseNode *pParseNode;
341 pParseNode = m_aSQLIterator.getOrderTree();
342 if (pParseNode != NULL)
344 if (SQL_ISRULE(pParseNode, opt_order_by_clause))
346 pParseNode = pParseNode->getChild(2);
347 KabOrder *pOrder = analyseOrderByClause(pParseNode);
348 pResult->sortKabAddressees(pOrder);
349 delete pOrder;
354 Any SAL_CALL KabCommonStatement::queryInterface( const Type & rType ) throw(RuntimeException, std::exception)
356 Any aRet = KabCommonStatement_BASE::queryInterface(rType);
357 if (!aRet.hasValue())
358 aRet = OPropertySetHelper::queryInterface(rType);
359 return aRet;
362 Sequence< Type > SAL_CALL KabCommonStatement::getTypes( ) throw(RuntimeException, std::exception)
364 ::cppu::OTypeCollection aTypes( cppu::UnoType<XMultiPropertySet>::get(),
365 cppu::UnoType<XFastPropertySet>::get(),
366 cppu::UnoType<XPropertySet>::get());
368 return comphelper::concatSequences(aTypes.getTypes(),KabCommonStatement_BASE::getTypes());
371 void SAL_CALL KabCommonStatement::cancel( ) throw(RuntimeException, std::exception)
373 ::osl::MutexGuard aGuard( m_aMutex );
375 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
376 // cancel the current sql statement
379 void SAL_CALL KabCommonStatement::close( ) throw(SQLException, RuntimeException, std::exception)
382 ::osl::MutexGuard aGuard( m_aMutex );
383 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
386 dispose();
389 sal_Bool SAL_CALL KabCommonStatement::execute(
390 const OUString& sql ) throw(SQLException, RuntimeException, std::exception)
392 ::osl::MutexGuard aGuard( m_aMutex );
393 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
395 Reference< XResultSet > xRS = executeQuery(sql);
397 return xRS.is();
400 Reference< XResultSet > SAL_CALL KabCommonStatement::executeQuery(
401 const OUString& sql ) throw(SQLException, RuntimeException, std::exception)
403 ::osl::MutexGuard aGuard( m_aMutex );
404 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
406 OSL_TRACE("KDE Address book - SQL Request: %s", OUtoCStr(sql));
408 KabResultSet* pResult = new KabResultSet(this);
409 Reference< XResultSet > xRS = pResult;
410 OUString aErr;
412 m_pParseTree = m_aParser.parseTree(aErr, sql);
413 if (m_pParseTree == NULL)
414 throw SQLException(aErr, *this, aErr, 0, Any());
416 m_aSQLIterator.setParseTree(m_pParseTree);
417 m_aSQLIterator.traverseAll();
418 switch (m_aSQLIterator.getStatementType())
420 case SQL_STATEMENT_SELECT:
421 if (isTableKnown(pResult)) // FROM which table ?
423 setKabFields(pResult); // SELECT which columns ?
424 selectAddressees(pResult); // WHERE which condition ?
425 sortAddressees(pResult); // ORDER BY which columns ?
426 // To be continued: DISTINCT
427 // etc...
429 break;
431 default:
432 // To be continued: UPDATE
433 // DELETE
434 // etc...
435 lcl_throwError(STR_QUERY_TOO_COMPLEX);
438 return xRS;
441 Reference< XConnection > SAL_CALL KabCommonStatement::getConnection( ) throw(SQLException, RuntimeException, std::exception)
443 ::osl::MutexGuard aGuard( m_aMutex );
444 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
446 // just return our connection here
447 return m_pConnection;
450 sal_Int32 SAL_CALL KabCommonStatement::executeUpdate( const OUString& ) throw(SQLException, RuntimeException, std::exception)
452 ::osl::MutexGuard aGuard( m_aMutex );
453 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
455 // the return values gives information about how many rows are affected by executing the sql statement
456 return 0;
459 Any SAL_CALL KabCommonStatement::getWarnings( ) throw(SQLException, RuntimeException, std::exception)
461 ::osl::MutexGuard aGuard( m_aMutex );
462 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
464 return makeAny(m_aLastWarning);
467 void SAL_CALL KabCommonStatement::clearWarnings( ) throw(SQLException, RuntimeException, std::exception)
469 ::osl::MutexGuard aGuard( m_aMutex );
470 checkDisposed(KabCommonStatement_BASE::rBHelper.bDisposed);
472 m_aLastWarning = SQLWarning();
475 ::cppu::IPropertyArrayHelper* KabCommonStatement::createArrayHelper( ) const
477 // this properties are defined by the service statement
478 // they must be in alphabetic order
479 Sequence< Property > aProps(10);
480 Property* pProperties = aProps.getArray();
481 sal_Int32 nPos = 0;
482 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME),
483 PROPERTY_ID_CURSORNAME, cppu::UnoType<OUString>::get(), 0);
484 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ESCAPEPROCESSING),
485 PROPERTY_ID_ESCAPEPROCESSING, cppu::UnoType<bool>::get(), 0);
486 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION),
487 PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0);
488 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE),
489 PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0);
490 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXFIELDSIZE),
491 PROPERTY_ID_MAXFIELDSIZE, cppu::UnoType<sal_Int32>::get(), 0);
492 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXROWS),
493 PROPERTY_ID_MAXROWS, cppu::UnoType<sal_Int32>::get(), 0);
494 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_QUERYTIMEOUT),
495 PROPERTY_ID_QUERYTIMEOUT, cppu::UnoType<sal_Int32>::get(), 0);
496 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY),
497 PROPERTY_ID_RESULTSETCONCURRENCY, cppu::UnoType<sal_Int32>::get(), 0);
498 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE),
499 PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), 0);
500 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_USEBOOKMARKS),
501 PROPERTY_ID_USEBOOKMARKS, cppu::UnoType<bool>::get(), 0);
503 return new ::cppu::OPropertyArrayHelper(aProps);
506 ::cppu::IPropertyArrayHelper & KabCommonStatement::getInfoHelper()
508 return *getArrayHelper();
511 sal_Bool KabCommonStatement::convertFastPropertyValue(
512 Any &,
513 Any &,
514 sal_Int32,
515 const Any&) throw (::com::sun::star::lang::IllegalArgumentException)
517 bool bConverted = false;
518 // here we have to try to convert
519 return bConverted;
522 void KabCommonStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any&) throw (Exception, std::exception)
524 // set the value to whatever is necessary
525 switch (nHandle)
527 case PROPERTY_ID_QUERYTIMEOUT:
528 case PROPERTY_ID_MAXFIELDSIZE:
529 case PROPERTY_ID_MAXROWS:
530 case PROPERTY_ID_CURSORNAME:
531 case PROPERTY_ID_RESULTSETCONCURRENCY:
532 case PROPERTY_ID_RESULTSETTYPE:
533 case PROPERTY_ID_FETCHDIRECTION:
534 case PROPERTY_ID_FETCHSIZE:
535 case PROPERTY_ID_ESCAPEPROCESSING:
536 case PROPERTY_ID_USEBOOKMARKS:
537 default:
542 void KabCommonStatement::getFastPropertyValue(Any&,sal_Int32 nHandle) const
544 switch (nHandle)
546 case PROPERTY_ID_QUERYTIMEOUT:
547 case PROPERTY_ID_MAXFIELDSIZE:
548 case PROPERTY_ID_MAXROWS:
549 case PROPERTY_ID_CURSORNAME:
550 case PROPERTY_ID_RESULTSETCONCURRENCY:
551 case PROPERTY_ID_RESULTSETTYPE:
552 case PROPERTY_ID_FETCHDIRECTION:
553 case PROPERTY_ID_FETCHSIZE:
554 case PROPERTY_ID_ESCAPEPROCESSING:
555 case PROPERTY_ID_USEBOOKMARKS:
556 default:
561 void SAL_CALL KabCommonStatement::acquire() throw()
563 KabCommonStatement_BASE::acquire();
566 void SAL_CALL KabCommonStatement::release() throw()
568 KabCommonStatement_BASE::release();
571 Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL KabCommonStatement::getPropertySetInfo( ) throw(RuntimeException, std::exception)
573 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
576 KabStatement::KabStatement(KabConnection* _pConnection)
577 : KabStatement_BASE(_pConnection)
581 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */