LibreOffice Module connectivity (master) 1
MacabStatement.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
21#include "MacabStatement.hxx"
22#include <sqlbison.hxx>
23#include "MacabConnection.hxx"
24#include "MacabAddressBook.hxx"
25#include "MacabDriver.hxx"
26#include "MacabResultSet.hxx"
28#include "macabcondition.hxx"
29#include "macaborder.hxx"
30#include "macabutilities.hxx"
31#include <TConnection.hxx>
35#include <rtl/ref.hxx>
36#include <strings.hrc>
37
38using namespace connectivity::macab;
39using namespace com::sun::star::uno;
40using namespace com::sun::star::lang;
41using namespace com::sun::star::beans;
42using namespace com::sun::star::sdbc;
43using namespace com::sun::star::sdbcx;
44using namespace com::sun::star::container;
45using namespace com::sun::star::io;
46using namespace com::sun::star::util;
47
48namespace connectivity::macab
49{
51 {
53 const OUString sError( aResources.getResourceString(pErrorId) );
55 }
56}
57
58IMPLEMENT_SERVICE_INFO(MacabStatement, "com.sun.star.sdbc.drivers.MacabStatement", "com.sun.star.sdbc.Statement");
59
60MacabCommonStatement::MacabCommonStatement(MacabConnection* _pConnection )
62 OPropertySetHelper(rBHelper),
63 m_aParser(_pConnection->getDriver()->getComponentContext()),
64 m_aSQLIterator(_pConnection, _pConnection->createCatalog()->getTables(), m_aParser ),
65 m_pParseTree(nullptr),
66 m_pConnection(_pConnection)
67{
68 m_pConnection->acquire();
69}
70
72{
73}
74
76{
77}
78
80{
81 impl_throwError(STR_PARA_ONLY_PREPARED);
82}
83
85{
86 if (pParseNode->count() == 3)
87 {
88 const OSQLParseNode *pLeft = pParseNode->getChild(0),
89 *pMiddle = pParseNode->getChild(1),
90 *pRight = pParseNode->getChild(2);
91
92 // WHERE ( ... ) ?
93 if (SQL_ISPUNCTUATION(pLeft, "(") && SQL_ISPUNCTUATION(pRight, ")"))
94 {
95 return analyseWhereClause(pMiddle);
96 }
97 else if (SQL_ISRULE(pParseNode, comparison_predicate))
98 {
99 if (pLeft->isToken() && pRight->isToken())
100 {
101 switch (pMiddle->getNodeType())
102 {
104 // WHERE 0 = 1
105 return new MacabConditionConstant(pLeft->getTokenValue() == pRight->getTokenValue());
106
108 // WHERE 0 <> 1
109 // (might not be correct SQL... don't care, handling anyway)
110 return new MacabConditionConstant(pLeft->getTokenValue() != pRight->getTokenValue());
111
112 default:
113 break;
114 }
115 }
116 else if (SQL_ISRULE(pLeft, column_ref))
117 {
118 OUString sColumnName,
119 sTableRange;
120
121 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange);
122
123 if (pRight->isToken() || SQL_ISRULE(pRight, parameter))
124 {
125 OUString sMatchString;
126
127 if (pRight->isToken()) // WHERE Name = 'Doe'
128 sMatchString = pRight->getTokenValue();
129 else if (SQL_ISRULE(pRight, parameter)) // WHERE Name = ?
130 getNextParameter(sMatchString);
131
132 switch (pMiddle->getNodeType())
133 {
135 // WHERE Name = 'Smith'
136 return new MacabConditionEqual(m_pHeader, sColumnName, sMatchString);
137
139 // WHERE Name <> 'Jones'
140 return new MacabConditionDifferent(m_pHeader, sColumnName, sMatchString);
141
142 default:
143 break;
144 }
145 }
146 }
147 }
148 else if (SQL_ISRULE(pParseNode, search_condition))
149 {
150 if (SQL_ISTOKEN(pMiddle, OR))
151 {
152 // WHERE Name = 'Smith' OR Name = 'Jones'
153 return new MacabConditionOr(
154 analyseWhereClause(pLeft),
155 analyseWhereClause(pRight));
156 }
157 }
158 else if (SQL_ISRULE(pParseNode, boolean_term))
159 {
160 if (SQL_ISTOKEN(pMiddle, AND))
161 {
162 // WHERE Name = 'Smith' AND "Given Name" = 'Peter'
163 return new MacabConditionAnd(
164 analyseWhereClause(pLeft),
165 analyseWhereClause(pRight));
166 }
167 }
168 }
169 else if (SQL_ISRULE(pParseNode, test_for_null) || SQL_ISRULE(pParseNode, like_predicate))
170 {
171 const OSQLParseNode *pLeft = pParseNode->getChild(0);
172 const OSQLParseNode* pPart2 = pParseNode->getChild(1);
173 const OSQLParseNode *pMiddleLeft = pPart2->getChild(0),
174 *pMiddleRight = pPart2->getChild(1),
175 *pRight = pPart2->getChild(2);
176
177 if (SQL_ISRULE(pParseNode, test_for_null))
178 {
179 if (SQL_ISRULE(pLeft, column_ref) &&
180 SQL_ISTOKEN(pMiddleLeft, IS) &&
181 SQL_ISTOKEN(pRight, NULL))
182 {
183 OUString sColumnName,
184 sTableRange;
185
186 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange);
187
188 if (SQL_ISTOKEN(pMiddleRight, NOT))
189 {
190 // WHERE "Mobile Phone" IS NOT NULL
191 return new MacabConditionNotNull(m_pHeader, sColumnName);
192 }
193 else
194 {
195 // WHERE "Mobile Phone" IS NULL
196 return new MacabConditionNull(m_pHeader, sColumnName);
197 }
198 }
199 }
200 else if (SQL_ISRULE(pParseNode, like_predicate))
201 {
202 if (SQL_ISRULE(pLeft, column_ref))
203 {
204 OUString sColumnName,
205 sTableRange;
206
207 m_aSQLIterator.getColumnRange(pLeft, sColumnName, sTableRange);
208
209 if (pMiddleRight->isToken() || SQL_ISRULE(pMiddleRight, parameter))
210 {
211 OUString sMatchString;
212
213 if (pMiddleRight->isToken()) // WHERE Name LIKE 'Sm%'
214 sMatchString = pMiddleRight->getTokenValue();
215 else if (SQL_ISRULE(pMiddleRight, parameter)) // WHERE Name LIKE ?
216 getNextParameter(sMatchString);
217
218 return new MacabConditionSimilar(m_pHeader, sColumnName, sMatchString);
219 }
220 }
221 }
222 }
223 impl_throwError(STR_QUERY_TOO_COMPLEX);
224 // Unreachable:
225 OSL_ASSERT(false);
226 return nullptr;
227}
228
230{
231 if (SQL_ISRULE(pParseNode, ordering_spec_commalist))
232 {
234 sal_uInt32 n = pParseNode->count();
235
236 // Iterate through the ordering columns
237 for (sal_uInt32 i = 0; i < n; i++)
238 {
239 list->addOrder
240 (analyseOrderByClause(pParseNode->getChild(i)));
241 }
242
243 return list;
244 }
245 else if (SQL_ISRULE(pParseNode, ordering_spec))
246 {
247 if (pParseNode->count() == 2)
248 {
249 OSQLParseNode* pColumnRef = pParseNode->getChild(0);
250 OSQLParseNode* pAscendingDescending = pParseNode->getChild(1);
251
252 if (SQL_ISRULE(pColumnRef, column_ref))
253 {
254 if (pColumnRef->count() == 3)
255 pColumnRef = pColumnRef->getChild(2);
256
257 if (pColumnRef->count() == 1)
258 {
259 OUString sColumnName =
260 pColumnRef->getChild(0)->getTokenValue();
261 bool bAscending =
262 !SQL_ISTOKEN(pAscendingDescending, DESC);
263
264 return new MacabSimpleOrder(m_pHeader, sColumnName, bAscending);
265 }
266 }
267 }
268 }
269 impl_throwError(STR_QUERY_TOO_COMPLEX);
270 // Unreachable:
271 OSL_ASSERT(false);
272 return nullptr;
273}
274
276{
277 const OSQLTables& xTabs = m_aSQLIterator.getTables();
278
279 if( xTabs.empty() )
280 return OUString();
281
282 // can only deal with one table at a time
283 if(xTabs.size() > 1 || m_aSQLIterator.hasErrors() )
284 return OUString();
285
286 return xTabs.begin()->first;
287}
288
290{
291 ::rtl::Reference<connectivity::OSQLColumns> xColumns; // selected columns
292 rtl::Reference<MacabResultSetMetaData> pMeta; // meta information - holds the list of AddressBook fields
293
294 xColumns = m_aSQLIterator.getSelectColumns();
295 if (!xColumns.is())
296 {
298 const OUString sError( aResources.getResourceString(
299 STR_INVALID_COLUMN_SELECTION
300 ) );
302 }
303 pMeta = static_cast<MacabResultSetMetaData *>(pResult->getMetaData().get());
304 pMeta->setMacabFields(xColumns);
305}
306
308{
309 const OSQLParseNode *pParseNode;
310
311 pParseNode = m_aSQLIterator.getWhereTree();
312 if (pParseNode != nullptr)
313 {
314 if (SQL_ISRULE(pParseNode, where_clause))
315 {
317 pParseNode = pParseNode->getChild(1);
318 MacabCondition *pCondition = analyseWhereClause(pParseNode);
319 if (pCondition->isAlwaysTrue())
320 pResult->allMacabRecords();
321 else
322 pResult->someMacabRecords(pCondition);
323 delete pCondition;
324 return;
325 }
326 }
327
328 // no WHERE clause: get all rows
329 pResult->allMacabRecords();
330}
331
333{
334 const OSQLParseNode *pParseNode;
335
336 pParseNode = m_aSQLIterator.getOrderTree();
337 if (pParseNode != nullptr)
338 {
339 if (SQL_ISRULE(pParseNode, opt_order_by_clause))
340 {
341 pParseNode = pParseNode->getChild(2);
342 MacabOrder *pOrder = analyseOrderByClause(pParseNode);
343 pResult->sortMacabRecords(pOrder);
344 delete pOrder;
345 }
346 }
347}
348
350{
351 Any aRet = MacabCommonStatement_BASE::queryInterface(rType);
352 if (!aRet.hasValue())
354 return aRet;
355}
356
358{
362
363 return comphelper::concatSequences(aTypes.getTypes(),MacabCommonStatement_BASE::getTypes());
364}
365
367{
368 ::osl::MutexGuard aGuard( m_aMutex );
369
371 // cancel the current sql statement
372}
373
375{
376 {
377 ::osl::MutexGuard aGuard( m_aMutex );
379
380 }
381 dispose();
382}
383
385 const OUString& sql )
386{
387 ::osl::MutexGuard aGuard( m_aMutex );
389
391
392 return xRS.is();
393}
394
396 const OUString& sql )
397{
398 ::osl::MutexGuard aGuard( m_aMutex );
400
402 OUString aErr;
403
404 m_pParseTree = m_aParser.parseTree(aErr, sql).release();
405 if (m_pParseTree == nullptr)
406 throw SQLException(aErr, *this, aErr, 0, Any());
407
411 {
413 {
414 OUString sTableName = getTableName(); // FROM which table ?
415 if (sTableName.getLength() != 0) // a match
416 {
417 MacabRecords *aRecords;
418 aRecords = m_pConnection->getAddressBook()->getMacabRecords(sTableName);
419
420 // In case, somehow, we don't have anything with the name m_sTableName
421 if(aRecords == nullptr)
422 {
423 impl_throwError(STR_NO_TABLE);
424 }
425 else
426 {
427 m_pHeader = aRecords->getHeader();
428
429 pResult->setTableName(sTableName);
430
431 setMacabFields(pResult.get()); // SELECT which columns ?
432 selectRecords(pResult.get()); // WHERE which condition ?
433 sortRecords(pResult.get()); // ORDER BY which columns ?
434 }
435// To be continued: DISTINCT
436// etc...
437 }
438 }
439 break;
440
441 default:
442// To be continued: UPDATE
443// DELETE
444// etc...
445 impl_throwError(STR_QUERY_TOO_COMPLEX);
446 }
447
449 return pResult;
450}
451
453{
454 ::osl::MutexGuard aGuard( m_aMutex );
456
457 // just return our connection here
458 return m_pConnection;
459}
460
461sal_Int32 SAL_CALL MacabCommonStatement::executeUpdate( const OUString& )
462{
463 ::osl::MutexGuard aGuard( m_aMutex );
465
466 // the return values gives information about how many rows are affected by executing the sql statement
467 return 0;
468}
469
471{
472 ::osl::MutexGuard aGuard( m_aMutex );
474
475 return Any(m_aLastWarning);
476}
477
479{
480 ::osl::MutexGuard aGuard( m_aMutex );
482
483 m_aLastWarning = SQLWarning();
484}
485
487{
488 // this properties are defined by the service statement
489 // they must be in alphabetic order
490 return new ::cppu::OPropertyArrayHelper
491 {
492 {
493 {
497 0
498 },
499 {
503 0
504 },
505 {
509 0
510 },
511 {
515 0
516 },
517 {
521 0
522 },
523 {
527 0
528 },
529 {
533 0
534 },
535 {
539 0
540 },
541 {
545 0
546 },
547 {
551 0
552 }
553 }
554 };
555}
556
558{
559 return *getArrayHelper();
560}
561
563 Any &,
564 Any &,
565 sal_Int32,
566 const Any&)
567{
568 // here we have to try to convert
569 return false;
570}
571
573{
574 // set the value to whatever is necessary
575 switch (nHandle)
576 {
587 default:
588 ;
589 }
590}
591
592void MacabCommonStatement::getFastPropertyValue(Any&,sal_Int32 nHandle) const
593{
594 switch (nHandle)
595 {
606 default:
607 ;
608 }
609}
610
611void SAL_CALL MacabCommonStatement::acquire() noexcept
612{
613 MacabCommonStatement_BASE::acquire();
614}
615
616void SAL_CALL MacabCommonStatement::release() noexcept
617{
618 MacabCommonStatement_BASE::release();
619}
620
622{
623 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
624}
625
627 : MacabStatement_BASE(_pConnection)
628{
629}
630
631/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
IMPLEMENT_SERVICE_INFO(MacabStatement, "com.sun.star.sdbc.drivers.MacabStatement", "com.sun.star.sdbc.Statement")
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
::dbtools::OPropertyMap & getPropMap()
Definition: TConnection.cxx:68
const OUString & getTokenValue() const
Definition: sqlnode.hxx:361
OSQLParseNode * getChild(sal_uInt32 nPos) const
Definition: sqlnode.hxx:433
const ::rtl::Reference< OSQLColumns > & getSelectColumns() const
const OSQLTables & getTables() const
void getColumnRange(const OSQLParseNode *_pColumnRef, OUString &_rColumnName, OUString &_rTableRange) const
return the columname and the table range
void setParseTree(const OSQLParseNode *pNewParseTree)
const OSQLParseNode * getOrderTree() const
OSQLStatementType getStatementType() const
void traverseAll()
traverses the complete statement tree, and fills all our data with the information obatined during tr...
const OSQLParseNode * getWhereTree() const
std::unique_ptr< OSQLParseNode > parseTree(OUString &rErrorMessage, const OUString &rStatement, bool bInternational=false)
helper class for accessing resources shared by different libraries in the connectivity module
OUString getResourceString(TranslateId pResId) const
loads a string from the shared resource file
virtual sal_Bool SAL_CALL execute(const OUString &sql) override
void selectRecords(MacabResultSet *pResult) const
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const css::uno::Any &rValue) override
virtual void SAL_CALL cancel() override
class MacabOrder * analyseOrderByClause(const OSQLParseNode *pParseNode) const
virtual ::cppu::IPropertyArrayHelper &SAL_CALL getInfoHelper() override
connectivity::OSQLParseNode * m_pParseTree
connectivity::OSQLParseTreeIterator m_aSQLIterator
virtual void SAL_CALL release() noexcept override
void sortRecords(MacabResultSet *pResult) const
virtual ::cppu::IPropertyArrayHelper * createArrayHelper() const override
virtual void getNextParameter(OUString &rParameter) const
virtual void SAL_CALL clearWarnings() override
virtual css::uno::Any SAL_CALL getWarnings() override
virtual sal_Bool SAL_CALL convertFastPropertyValue(css::uno::Any &rConvertedValue, css::uno::Any &rOldValue, sal_Int32 nHandle, const css::uno::Any &rValue) override
void setMacabFields(class MacabResultSet *pResult) const
virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection() override
virtual void SAL_CALL acquire() noexcept override
virtual sal_Int32 SAL_CALL executeUpdate(const OUString &sql) override
class MacabCondition * analyseWhereClause(const OSQLParseNode *pParseNode) const
css::uno::WeakReference< css::sdbc::XResultSet > m_xResultSet
virtual void SAL_CALL getFastPropertyValue(css::uno::Any &rValue, sal_Int32 nHandle) const override
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
virtual void SAL_CALL close() override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL executeQuery(const OUString &sql) override
void addOrder(MacabOrder *pOrder)
Definition: macaborder.cxx:59
virtual bool isAlwaysTrue() const =0
MacabAddressBook * getAddressBook() const
MacabHeader * getHeader() const
void sortMacabRecords(const class MacabOrder *pOrder)
void someMacabRecords(const class MacabCondition *pCondition)
virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData() override
MacabStatement(MacabConnection *_pConnection)
mutable::osl::Mutex m_aMutex
OBroadcastHelper & rBHelper
css::uno::Type const & get()
const OUString & getNameByIndex(sal_Int32 _nIndex) const
Definition: propertyids.cxx:95
std::mutex m_aMutex
sal_Int64 n
css::uno::Sequence< T > concatSequences(const css::uno::Sequence< T > &rS1, const Ss &... rSn)
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
Type
::cppu::WeakComponentImplHelper< css::sdbc::XStatement, css::sdbc::XWarningsSupplier, css::util::XCancellable, css::sdbc::XCloseable > MacabCommonStatement_BASE
void impl_throwError(TranslateId pErrorId)
::cppu::ImplInheritanceHelper< MacabCommonStatement, css::lang::XServiceInfo > MacabStatement_BASE
std::map< OUString, OSQLTable, comphelper::UStringMixLess > OSQLTables
Definition: CommonTools.hxx:56
void checkDisposed(bool _bThrow)
Definition: dbtools.cxx:1951
void throwGenericSQLException(const OUString &_rMsg, const css::uno::Reference< css::uno::XInterface > &_rxSource)
throw a generic SQLException, i.e.
int i
void dispose()
#define PROPERTY_ID_RESULTSETTYPE
Definition: propertyids.hxx:44
#define PROPERTY_ID_QUERYTIMEOUT
Definition: propertyids.hxx:39
#define PROPERTY_ID_USEBOOKMARKS
Definition: propertyids.hxx:48
#define PROPERTY_ID_CURSORNAME
Definition: propertyids.hxx:42
#define PROPERTY_ID_RESULTSETCONCURRENCY
Definition: propertyids.hxx:43
#define PROPERTY_ID_MAXFIELDSIZE
Definition: propertyids.hxx:40
#define PROPERTY_ID_FETCHSIZE
Definition: propertyids.hxx:46
#define PROPERTY_ID_MAXROWS
Definition: propertyids.hxx:41
#define PROPERTY_ID_ESCAPEPROCESSING
Definition: propertyids.hxx:47
#define PROPERTY_ID_FETCHDIRECTION
Definition: propertyids.hxx:45
sal_Int32 nHandle
#define SQL_ISRULE(pParseNode, eRule)
Definition: sqlnode.hxx:439
#define SQL_ISPUNCTUATION(pParseNode, aString)
Definition: sqlnode.hxx:450
#define SQL_ISTOKEN(pParseNode, token)
Definition: sqlnode.hxx:447
unsigned char sal_Bool
const SvXMLTokenMapEntry aTypes[]