/src/libreoffice/connectivity/source/drivers/file/FStatement.cxx
Line | Count | Source (jump to first uncovered line) |
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 | | #include <sal/config.h> |
21 | | |
22 | | #include <o3tl/safeint.hxx> |
23 | | #include <osl/diagnose.h> |
24 | | #include <file/FStatement.hxx> |
25 | | #include <file/FConnection.hxx> |
26 | | #include <sqlbison.hxx> |
27 | | #include <file/FDriver.hxx> |
28 | | #include <file/FResultSet.hxx> |
29 | | #include <sal/log.hxx> |
30 | | #include <com/sun/star/sdbc/ResultSetConcurrency.hpp> |
31 | | #include <com/sun/star/sdbc/ResultSetType.hpp> |
32 | | #include <com/sun/star/sdbc/FetchDirection.hpp> |
33 | | #include <com/sun/star/lang/DisposedException.hpp> |
34 | | #include <comphelper/sequence.hxx> |
35 | | #include <comphelper/servicehelper.hxx> |
36 | | #include <cppuhelper/typeprovider.hxx> |
37 | | #include <comphelper/types.hxx> |
38 | | #include <connectivity/dbexception.hxx> |
39 | | #include <strings.hrc> |
40 | | #include <algorithm> |
41 | | #include <cstddef> |
42 | | |
43 | | namespace connectivity::file |
44 | | { |
45 | | |
46 | | |
47 | | using namespace dbtools; |
48 | | using namespace com::sun::star::uno; |
49 | | using namespace com::sun::star::lang; |
50 | | using namespace com::sun::star::beans; |
51 | | using namespace com::sun::star::sdbc; |
52 | | using namespace com::sun::star::sdbcx; |
53 | | using namespace com::sun::star::container; |
54 | | |
55 | | OStatement_Base::OStatement_Base(OConnection* _pConnection ) |
56 | 29.1k | :OStatement_BASE(m_aMutex) |
57 | 29.1k | ,::comphelper::OPropertyContainer(OStatement_BASE::rBHelper) |
58 | 29.1k | ,m_xDBMetaData(_pConnection->getMetaData()) |
59 | 29.1k | ,m_aParser( _pConnection->getDriver()->getComponentContext() ) |
60 | 29.1k | ,m_aSQLIterator( _pConnection, _pConnection->createCatalog()->getTables(), m_aParser ) |
61 | 29.1k | ,m_pConnection(_pConnection) |
62 | 29.1k | ,m_pParseTree(nullptr) |
63 | 29.1k | ,m_nMaxFieldSize(0) |
64 | 29.1k | ,m_nMaxRows(0) |
65 | 29.1k | ,m_nQueryTimeOut(0) |
66 | 29.1k | ,m_nFetchSize(0) |
67 | 29.1k | ,m_nResultSetType(ResultSetType::FORWARD_ONLY) |
68 | 29.1k | ,m_nFetchDirection(FetchDirection::FORWARD) |
69 | 29.1k | ,m_nResultSetConcurrency(ResultSetConcurrency::UPDATABLE) |
70 | 29.1k | ,m_bEscapeProcessing(true) |
71 | 29.1k | { |
72 | 29.1k | sal_Int32 nAttrib = 0; |
73 | | |
74 | 29.1k | registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME), PROPERTY_ID_CURSORNAME, nAttrib,&m_aCursorName, ::cppu::UnoType<OUString>::get()); |
75 | 29.1k | registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXFIELDSIZE), PROPERTY_ID_MAXFIELDSIZE, nAttrib,&m_nMaxFieldSize, ::cppu::UnoType<sal_Int32>::get()); |
76 | 29.1k | registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXROWS), PROPERTY_ID_MAXROWS, nAttrib,&m_nMaxRows, ::cppu::UnoType<sal_Int32>::get()); |
77 | 29.1k | registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_QUERYTIMEOUT), PROPERTY_ID_QUERYTIMEOUT, nAttrib,&m_nQueryTimeOut, ::cppu::UnoType<sal_Int32>::get()); |
78 | 29.1k | registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE), PROPERTY_ID_FETCHSIZE, nAttrib,&m_nFetchSize, ::cppu::UnoType<sal_Int32>::get()); |
79 | 29.1k | registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE), PROPERTY_ID_RESULTSETTYPE, nAttrib,&m_nResultSetType, ::cppu::UnoType<sal_Int32>::get()); |
80 | 29.1k | registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION), PROPERTY_ID_FETCHDIRECTION, nAttrib,&m_nFetchDirection, ::cppu::UnoType<sal_Int32>::get()); |
81 | 29.1k | registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ESCAPEPROCESSING),PROPERTY_ID_ESCAPEPROCESSING, nAttrib,&m_bEscapeProcessing,cppu::UnoType<bool>::get()); |
82 | | |
83 | 29.1k | registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY), PROPERTY_ID_RESULTSETCONCURRENCY, nAttrib,&m_nResultSetConcurrency, ::cppu::UnoType<sal_Int32>::get()); |
84 | 29.1k | } |
85 | | |
86 | | OStatement_Base::~OStatement_Base() |
87 | 29.1k | { |
88 | 29.1k | osl_atomic_increment( &m_refCount ); |
89 | 29.1k | disposing(); |
90 | 29.1k | } |
91 | | |
92 | | void OStatement_Base::disposeResultSet() |
93 | 29.1k | { |
94 | 29.1k | SAL_INFO( "connectivity.drivers", "file Ocke.Janssen@sun.com OStatement_Base::disposeResultSet" ); |
95 | | // free the cursor if alive |
96 | 29.1k | rtl::Reference< OResultSet > xComp(m_xResultSet.get()); |
97 | 29.1k | assert(xComp.is() || !m_xResultSet.get().is()); |
98 | 29.1k | if (xComp.is()) |
99 | 19.3k | xComp->dispose(); |
100 | 29.1k | m_xResultSet.clear(); |
101 | 29.1k | } |
102 | | |
103 | | void OStatement_BASE2::disposing() |
104 | 29.1k | { |
105 | 29.1k | ::osl::MutexGuard aGuard(m_aMutex); |
106 | | |
107 | 29.1k | disposeResultSet(); |
108 | | |
109 | 29.1k | if(m_pSQLAnalyzer) |
110 | 28.9k | m_pSQLAnalyzer->dispose(); |
111 | | |
112 | 29.1k | if(m_aRow.is()) |
113 | 28.9k | { |
114 | 28.9k | m_aRow->clear(); |
115 | 28.9k | m_aRow = nullptr; |
116 | 28.9k | } |
117 | | |
118 | 29.1k | m_aSQLIterator.dispose(); |
119 | | |
120 | 29.1k | m_pTable.clear(); |
121 | | |
122 | 29.1k | m_pConnection.clear(); |
123 | | |
124 | 29.1k | if ( m_pParseTree ) |
125 | 29.1k | { |
126 | 29.1k | delete m_pParseTree; |
127 | 29.1k | m_pParseTree = nullptr; |
128 | 29.1k | } |
129 | | |
130 | 29.1k | OStatement_Base::disposing(); |
131 | 29.1k | } |
132 | | |
133 | | void SAL_CALL OStatement_Base::acquire() noexcept |
134 | 435k | { |
135 | 435k | OStatement_BASE::acquire(); |
136 | 435k | } |
137 | | |
138 | | void SAL_CALL OStatement_BASE2::release() noexcept |
139 | 435k | { |
140 | 435k | OStatement_BASE::release(); |
141 | 435k | } |
142 | | |
143 | | Any SAL_CALL OStatement_Base::queryInterface( const Type & rType ) |
144 | 125k | { |
145 | 125k | const Any aRet = OStatement_BASE::queryInterface(rType); |
146 | 125k | return aRet.hasValue() ? aRet : OPropertySetHelper::queryInterface(rType); |
147 | 125k | } |
148 | | |
149 | | Sequence< Type > SAL_CALL OStatement_Base::getTypes( ) |
150 | 0 | { |
151 | 0 | ::cppu::OTypeCollection aTypes( cppu::UnoType<css::beans::XMultiPropertySet>::get(), |
152 | 0 | cppu::UnoType<css::beans::XFastPropertySet>::get(), |
153 | 0 | cppu::UnoType<css::beans::XPropertySet>::get()); |
154 | |
|
155 | 0 | return ::comphelper::concatSequences(aTypes.getTypes(),OStatement_BASE::getTypes()); |
156 | 0 | } |
157 | | |
158 | | |
159 | | void SAL_CALL OStatement_Base::cancel( ) |
160 | 0 | { |
161 | 0 | } |
162 | | |
163 | | void SAL_CALL OStatement_Base::close() |
164 | 0 | { |
165 | 0 | { |
166 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
167 | 0 | checkDisposed(OStatement_BASE::rBHelper.bDisposed); |
168 | 0 | } |
169 | 0 | dispose(); |
170 | 0 | } |
171 | | |
172 | | void OStatement_Base::closeResultSet() |
173 | 9.65k | { |
174 | 9.65k | SAL_INFO( "connectivity.drivers", "file Ocke.Janssen@sun.com OStatement_Base::clearMyResultSet " ); |
175 | 9.65k | ::osl::MutexGuard aGuard( m_aMutex ); |
176 | 9.65k | checkDisposed(OStatement_BASE::rBHelper.bDisposed); |
177 | | |
178 | 9.65k | rtl::Reference< OResultSet > xCloseable(m_xResultSet.get()); |
179 | 9.65k | assert(xCloseable.is() || !m_xResultSet.get().is()); |
180 | 9.65k | if (xCloseable.is()) |
181 | 0 | { |
182 | 0 | try |
183 | 0 | { |
184 | 0 | xCloseable->close(); |
185 | 0 | } |
186 | 0 | catch( const DisposedException& ) { } |
187 | 0 | } |
188 | | |
189 | 9.65k | m_xResultSet.clear(); |
190 | 9.65k | } |
191 | | |
192 | | Any SAL_CALL OStatement_Base::getWarnings( ) |
193 | 0 | { |
194 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
195 | 0 | checkDisposed(OStatement_BASE::rBHelper.bDisposed); |
196 | |
|
197 | 0 | return Any(m_aLastWarning); |
198 | 0 | } |
199 | | |
200 | | void SAL_CALL OStatement_Base::clearWarnings( ) |
201 | 0 | { |
202 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
203 | 0 | checkDisposed(OStatement_BASE::rBHelper.bDisposed); |
204 | |
|
205 | 0 | m_aLastWarning = SQLWarning(); |
206 | 0 | } |
207 | | |
208 | | ::cppu::IPropertyArrayHelper* OStatement_Base::createArrayHelper( ) const |
209 | 19.3k | { |
210 | 19.3k | Sequence< Property > aProps; |
211 | 19.3k | describeProperties(aProps); |
212 | 19.3k | return new ::cppu::OPropertyArrayHelper(aProps); |
213 | 19.3k | } |
214 | | |
215 | | |
216 | | ::cppu::IPropertyArrayHelper & OStatement_Base::getInfoHelper() |
217 | 48.4k | { |
218 | 48.4k | return *getArrayHelper(); |
219 | 48.4k | } |
220 | | |
221 | | rtl::Reference<OResultSet> OStatement::createResultSet() |
222 | 0 | { |
223 | 0 | return new OResultSet(this,m_aSQLIterator); |
224 | 0 | } |
225 | | |
226 | | IMPLEMENT_SERVICE_INFO(OStatement,u"com.sun.star.sdbc.driver.file.Statement"_ustr,u"com.sun.star.sdbc.Statement"_ustr); |
227 | | |
228 | | void SAL_CALL OStatement::acquire() noexcept |
229 | 116k | { |
230 | 116k | OStatement_BASE2::acquire(); |
231 | 116k | } |
232 | | |
233 | | void SAL_CALL OStatement::release() noexcept |
234 | 116k | { |
235 | 116k | OStatement_BASE2::release(); |
236 | 116k | } |
237 | | |
238 | | |
239 | | sal_Bool SAL_CALL OStatement::execute( const OUString& sql ) |
240 | 0 | { |
241 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
242 | |
|
243 | 0 | executeQuery(sql); |
244 | |
|
245 | 0 | return m_aSQLIterator.getStatementType() == OSQLStatementType::Select; |
246 | 0 | } |
247 | | |
248 | | |
249 | | Reference< XResultSet > SAL_CALL OStatement::executeQuery( const OUString& sql ) |
250 | 9.70k | { |
251 | 9.70k | ::osl::MutexGuard aGuard( m_aMutex ); |
252 | 9.70k | checkDisposed(OStatement_BASE::rBHelper.bDisposed); |
253 | | |
254 | 9.70k | construct(sql); |
255 | 9.70k | rtl::Reference<OResultSet> pResult = createResultSet(); |
256 | 9.70k | initializeResultSet(pResult.get()); |
257 | 9.70k | m_xResultSet = pResult.get(); |
258 | | |
259 | 9.70k | pResult->OpenImpl(); |
260 | | |
261 | 9.70k | return pResult; |
262 | 9.70k | } |
263 | | |
264 | | Reference< XConnection > SAL_CALL OStatement::getConnection( ) |
265 | 0 | { |
266 | 0 | return m_pConnection; |
267 | 0 | } |
268 | | |
269 | | sal_Int32 SAL_CALL OStatement::executeUpdate( const OUString& sql ) |
270 | 0 | { |
271 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
272 | 0 | checkDisposed(OStatement_BASE::rBHelper.bDisposed); |
273 | | |
274 | |
|
275 | 0 | construct(sql); |
276 | 0 | rtl::Reference<OResultSet> pResult = createResultSet(); |
277 | 0 | initializeResultSet(pResult.get()); |
278 | 0 | pResult->OpenImpl(); |
279 | |
|
280 | 0 | return pResult->getRowCountResult(); |
281 | 0 | } |
282 | | |
283 | | |
284 | | void SAL_CALL OStatement_Base::disposing() |
285 | 58.2k | { |
286 | 58.2k | if(m_aEvaluateRow.is()) |
287 | 28.9k | { |
288 | 28.9k | m_aEvaluateRow->clear(); |
289 | 28.9k | m_aEvaluateRow = nullptr; |
290 | 28.9k | } |
291 | 58.2k | OStatement_BASE::disposing(); |
292 | 58.2k | } |
293 | | |
294 | | Reference< css::beans::XPropertySetInfo > SAL_CALL OStatement_Base::getPropertySetInfo( ) |
295 | 0 | { |
296 | 0 | return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); |
297 | 0 | } |
298 | | |
299 | | Any SAL_CALL OStatement::queryInterface( const Type & rType ) |
300 | 38.8k | { |
301 | 38.8k | Any aRet = OStatement_XStatement::queryInterface( rType); |
302 | 38.8k | return aRet.hasValue() ? aRet : OStatement_BASE2::queryInterface( rType); |
303 | 38.8k | } |
304 | | |
305 | | void OStatement_Base::analyzeSQL() |
306 | 28.9k | { |
307 | 28.9k | OSL_ENSURE(m_pSQLAnalyzer,"OResultSet::analyzeSQL: Analyzer isn't set!"); |
308 | | // start analysing the statement |
309 | 28.9k | m_pSQLAnalyzer->setOrigColumns(m_xColNames); |
310 | 28.9k | m_pSQLAnalyzer->start(m_pParseTree); |
311 | | |
312 | 28.9k | const OSQLParseNode* pOrderbyClause = m_aSQLIterator.getOrderTree(); |
313 | 28.9k | if(!pOrderbyClause) |
314 | 28.9k | return; |
315 | | |
316 | 0 | OSQLParseNode * pOrderingSpecCommalist = pOrderbyClause->getChild(2); |
317 | 0 | OSL_ENSURE(SQL_ISRULE(pOrderingSpecCommalist,ordering_spec_commalist),"OResultSet: Error in Parse Tree"); |
318 | |
|
319 | 0 | for (size_t m = 0; m < pOrderingSpecCommalist->count(); m++) |
320 | 0 | { |
321 | 0 | OSQLParseNode * pOrderingSpec = pOrderingSpecCommalist->getChild(m); |
322 | 0 | OSL_ENSURE(SQL_ISRULE(pOrderingSpec,ordering_spec),"OResultSet: Error in Parse Tree"); |
323 | 0 | OSL_ENSURE(pOrderingSpec->count() == 2,"OResultSet: Error in Parse Tree"); |
324 | |
|
325 | 0 | OSQLParseNode * pColumnRef = pOrderingSpec->getChild(0); |
326 | 0 | if(!SQL_ISRULE(pColumnRef,column_ref)) |
327 | 0 | { |
328 | 0 | throw SQLException(); |
329 | 0 | } |
330 | 0 | OSQLParseNode * pAscendingDescending = pOrderingSpec->getChild(1); |
331 | 0 | setOrderbyColumn(pColumnRef,pAscendingDescending); |
332 | 0 | } |
333 | 0 | } |
334 | | |
335 | | void OStatement_Base::setOrderbyColumn( OSQLParseNode const * pColumnRef, |
336 | | OSQLParseNode const * pAscendingDescending) |
337 | 0 | { |
338 | 0 | OUString aColumnName; |
339 | 0 | if (pColumnRef->count() == 1) |
340 | 0 | aColumnName = pColumnRef->getChild(0)->getTokenValue(); |
341 | 0 | else if (pColumnRef->count() == 3) |
342 | 0 | { |
343 | 0 | pColumnRef->getChild(2)->parseNodeToStr( aColumnName, getOwnConnection(), nullptr, false, false ); |
344 | 0 | } |
345 | 0 | else |
346 | 0 | { |
347 | 0 | throw SQLException(); |
348 | 0 | } |
349 | | |
350 | 0 | Reference<XColumnLocate> xColLocate(m_xColNames,UNO_QUERY); |
351 | 0 | if(!xColLocate.is()) |
352 | 0 | return; |
353 | | // Everything tested and we have the name of the Column. |
354 | | // What number is the Column? |
355 | 0 | ::rtl::Reference<OSQLColumns> aSelectColumns = m_aSQLIterator.getSelectColumns(); |
356 | 0 | ::comphelper::UStringMixEqual aCase; |
357 | 0 | OSQLColumns::const_iterator aFind = ::connectivity::find(aSelectColumns->begin(),aSelectColumns->end(),aColumnName,aCase); |
358 | 0 | if ( aFind == aSelectColumns->end() ) |
359 | 0 | throw SQLException(); |
360 | 0 | m_aOrderbyColumnNumber.push_back((aFind - aSelectColumns->begin()) + 1); |
361 | | |
362 | | // Ascending or Descending? |
363 | 0 | m_aOrderbyAscending.push_back(SQL_ISTOKEN(pAscendingDescending,DESC) ? TAscendingOrder::DESC : TAscendingOrder::ASC); |
364 | 0 | } |
365 | | |
366 | | void OStatement_Base::construct(const OUString& sql) |
367 | 29.1k | { |
368 | 29.1k | OUString aErr; |
369 | 29.1k | m_pParseTree = m_aParser.parseTree(aErr,sql).release(); |
370 | 29.1k | if(!m_pParseTree) |
371 | 0 | throw SQLException(aErr,*this,OUString(),0,Any()); |
372 | | |
373 | 29.1k | m_aSQLIterator.setParseTree(m_pParseTree); |
374 | 29.1k | m_aSQLIterator.traverseAll(); |
375 | 29.1k | const OSQLTables& rTabs = m_aSQLIterator.getTables(); |
376 | | |
377 | | // sanity checks |
378 | 29.1k | if ( rTabs.empty() ) |
379 | | // no tables -> nothing to operate on -> error |
380 | 0 | m_pConnection->throwGenericSQLException(STR_QUERY_NO_TABLE,*this); |
381 | | |
382 | 29.1k | if ( rTabs.size() > 1 || m_aSQLIterator.hasErrors() ) |
383 | | // more than one table -> can't operate on them -> error |
384 | 0 | m_pConnection->throwGenericSQLException(STR_QUERY_MORE_TABLES,*this); |
385 | | |
386 | 29.1k | if ( (m_aSQLIterator.getStatementType() == OSQLStatementType::Select) && m_aSQLIterator.getSelectColumns()->empty() ) |
387 | | // SELECT statement without columns -> error |
388 | 144 | m_pConnection->throwGenericSQLException(STR_QUERY_NO_COLUMN,*this); |
389 | | |
390 | 29.1k | switch(m_aSQLIterator.getStatementType()) |
391 | 29.1k | { |
392 | 0 | case OSQLStatementType::CreateTable: |
393 | 0 | case OSQLStatementType::OdbcCall: |
394 | 0 | case OSQLStatementType::Unknown: |
395 | 0 | m_pConnection->throwGenericSQLException(STR_QUERY_TOO_COMPLEX,*this); |
396 | 0 | break; |
397 | 28.9k | case OSQLStatementType::Select: |
398 | 28.9k | if(SQL_ISRULE(m_aSQLIterator.getParseTree(), union_statement)) |
399 | 0 | { |
400 | 0 | m_pConnection->throwGenericSQLException(STR_QUERY_TOO_COMPLEX, *this); |
401 | 0 | } |
402 | 28.9k | assert(SQL_ISRULE(m_aSQLIterator.getParseTree(), select_statement)); |
403 | 28.9k | break; |
404 | 0 | default: |
405 | 0 | break; |
406 | 29.1k | } |
407 | | |
408 | | // at this moment we support only one table per select statement |
409 | 28.9k | m_pTable = dynamic_cast<OFileTable*>(rTabs.begin()->second.get()); |
410 | 28.9k | OSL_ENSURE(m_pTable.is(),"No table!"); |
411 | 28.9k | if ( m_pTable.is() ) |
412 | 28.9k | m_xColNames = m_pTable->getColumns(); |
413 | 28.9k | Reference<XIndexAccess> xNames(m_xColNames,UNO_QUERY); |
414 | | // set the binding of the resultrow |
415 | 28.9k | m_aRow = new OValueRefVector(xNames->getCount()); |
416 | 28.9k | (*m_aRow)[0]->setBound(true); |
417 | 28.9k | std::for_each(m_aRow->begin()+1,m_aRow->end(),TSetRefBound(false)); |
418 | | |
419 | | // set the binding of the resultrow |
420 | 28.9k | m_aEvaluateRow = new OValueRefVector(xNames->getCount()); |
421 | | |
422 | 28.9k | (*m_aEvaluateRow)[0]->setBound(true); |
423 | 28.9k | std::for_each(m_aEvaluateRow->begin()+1,m_aEvaluateRow->end(),TSetRefBound(false)); |
424 | | |
425 | | // set the select row |
426 | 28.9k | m_aSelectRow = new OValueRefVector(m_aSQLIterator.getSelectColumns()->size()); |
427 | 28.9k | std::for_each(m_aSelectRow->begin(),m_aSelectRow->end(),TSetRefBound(true)); |
428 | | |
429 | | // create the column mapping |
430 | 28.9k | createColumnMapping(); |
431 | | |
432 | 28.9k | m_pSQLAnalyzer.reset( new OSQLAnalyzer(m_pConnection.get()) ); |
433 | | |
434 | 28.9k | analyzeSQL(); |
435 | 28.9k | } |
436 | | |
437 | | void OStatement_Base::createColumnMapping() |
438 | 28.9k | { |
439 | | // initialize the column index map (mapping select columns to table columns) |
440 | 28.9k | ::rtl::Reference<connectivity::OSQLColumns> xColumns = m_aSQLIterator.getSelectColumns(); |
441 | 28.9k | m_aColMapping.resize(xColumns->size() + 1); |
442 | 990k | for (std::size_t i=0; i<m_aColMapping.size(); ++i) |
443 | 961k | m_aColMapping[i] = i; |
444 | | |
445 | 28.9k | Reference<XIndexAccess> xNames(m_xColNames,UNO_QUERY); |
446 | | // now check which columns are bound |
447 | 28.9k | OResultSet::setBoundedColumns(m_aRow,m_aSelectRow,xColumns,xNames,true,m_xDBMetaData,m_aColMapping); |
448 | 28.9k | } |
449 | | |
450 | | void OStatement_Base::initializeResultSet(OResultSet* _pResult) |
451 | 19.3k | { |
452 | 19.3k | GetAssignValues(); |
453 | | |
454 | 19.3k | _pResult->setSqlAnalyzer(m_pSQLAnalyzer.get()); |
455 | 19.3k | _pResult->setOrderByColumns(std::vector(m_aOrderbyColumnNumber)); |
456 | 19.3k | _pResult->setOrderByAscending(std::vector(m_aOrderbyAscending)); |
457 | 19.3k | _pResult->setBindingRow(m_aRow); |
458 | 19.3k | _pResult->setColumnMapping(std::vector(m_aColMapping)); |
459 | 19.3k | _pResult->setEvaluationRow(m_aEvaluateRow); |
460 | 19.3k | _pResult->setAssignValues(m_aAssignValues); |
461 | 19.3k | _pResult->setSelectRow(m_aSelectRow); |
462 | | |
463 | 19.3k | m_pSQLAnalyzer->bindSelectRow(m_aRow); |
464 | 19.3k | m_pSQLAnalyzer->bindEvaluationRow(m_aEvaluateRow); // Set values in the code of the Compiler |
465 | 19.3k | } |
466 | | |
467 | | void OStatement_Base::GetAssignValues() |
468 | 19.3k | { |
469 | 19.3k | if (m_pParseTree == nullptr) |
470 | 0 | { |
471 | 0 | ::dbtools::throwFunctionSequenceException(*this); |
472 | 0 | return; |
473 | 0 | } |
474 | | |
475 | 19.3k | if (SQL_ISRULE(m_pParseTree,select_statement)) |
476 | | // no values have to be set for SELECT |
477 | 19.3k | return; |
478 | 0 | else if (SQL_ISRULE(m_pParseTree,insert_statement)) |
479 | 0 | { |
480 | | // Create Row for the values to be set (Reference through new) |
481 | 0 | if(m_aAssignValues.is()) |
482 | 0 | m_aAssignValues->clear(); |
483 | 0 | sal_Int32 nCount = Reference<XIndexAccess>(m_xColNames,UNO_QUERY_THROW)->getCount(); |
484 | 0 | m_aAssignValues = new OAssignValues(nCount); |
485 | | // unbound all |
486 | 0 | std::for_each(m_aAssignValues->begin()+1,m_aAssignValues->end(),TSetRefBound(false)); |
487 | |
|
488 | 0 | m_aParameterIndexes.resize(nCount+1,SQL_NO_PARAMETER); |
489 | | |
490 | | // List of Column-Names, that exist in the column_commalist (separated by ;): |
491 | 0 | std::vector<OUString> aColumnNameList; |
492 | |
|
493 | 0 | OSL_ENSURE(m_pParseTree->count() >= 4,"OResultSet: Error in Parse Tree"); |
494 | |
|
495 | 0 | OSQLParseNode * pOptColumnCommalist = m_pParseTree->getChild(3); |
496 | 0 | OSL_ENSURE(pOptColumnCommalist != nullptr,"OResultSet: Error in Parse Tree"); |
497 | 0 | OSL_ENSURE(SQL_ISRULE(pOptColumnCommalist,opt_column_commalist),"OResultSet: Error in Parse Tree"); |
498 | 0 | if (pOptColumnCommalist->count() == 0) |
499 | 0 | { |
500 | 0 | const Sequence< OUString> aNames = m_xColNames->getElementNames(); |
501 | 0 | aColumnNameList.insert(aColumnNameList.end(), aNames.begin(), aNames.end()); |
502 | 0 | } |
503 | 0 | else |
504 | 0 | { |
505 | 0 | OSL_ENSURE(pOptColumnCommalist->count() == 3,"OResultSet: Error in Parse Tree"); |
506 | |
|
507 | 0 | OSQLParseNode * pColumnCommalist = pOptColumnCommalist->getChild(1); |
508 | 0 | OSL_ENSURE(pColumnCommalist != nullptr,"OResultSet: Error in Parse Tree"); |
509 | 0 | OSL_ENSURE(SQL_ISRULE(pColumnCommalist,column_commalist),"OResultSet: Error in Parse Tree"); |
510 | 0 | OSL_ENSURE(pColumnCommalist->count() > 0,"OResultSet: Error in Parse Tree"); |
511 | | |
512 | | // All Columns in the column_commalist ... |
513 | 0 | for (size_t i = 0; i < pColumnCommalist->count(); i++) |
514 | 0 | { |
515 | 0 | OSQLParseNode * pCol = pColumnCommalist->getChild(i); |
516 | 0 | OSL_ENSURE(pCol != nullptr,"OResultSet: Error in Parse Tree"); |
517 | 0 | aColumnNameList.push_back(pCol->getTokenValue()); |
518 | 0 | } |
519 | 0 | } |
520 | 0 | if ( aColumnNameList.empty() ) |
521 | 0 | throwFunctionSequenceException(*this); |
522 | | |
523 | | // Values ... |
524 | 0 | OSQLParseNode * pValuesOrQuerySpec = m_pParseTree->getChild(4); |
525 | 0 | OSL_ENSURE(pValuesOrQuerySpec != nullptr,"OResultSet: pValuesOrQuerySpec must not be NULL!"); |
526 | 0 | OSL_ENSURE(SQL_ISRULE(pValuesOrQuerySpec,values_or_query_spec),"OResultSet: ! SQL_ISRULE(pValuesOrQuerySpec,values_or_query_spec)"); |
527 | 0 | OSL_ENSURE(pValuesOrQuerySpec->count() > 0,"OResultSet: pValuesOrQuerySpec->count() <= 0"); |
528 | | |
529 | | // just "VALUES" is allowed ... |
530 | 0 | if (! SQL_ISTOKEN(pValuesOrQuerySpec->getChild(0),VALUES)) |
531 | 0 | throwFunctionSequenceException(*this); |
532 | |
|
533 | 0 | OSL_ENSURE(pValuesOrQuerySpec->count() == 4,"OResultSet: pValuesOrQuerySpec->count() != 4"); |
534 | | |
535 | | // List of values |
536 | 0 | OSQLParseNode * pInsertAtomCommalist = pValuesOrQuerySpec->getChild(2); |
537 | 0 | OSL_ENSURE(pInsertAtomCommalist != nullptr,"OResultSet: pInsertAtomCommalist must not be NULL!"); |
538 | 0 | OSL_ENSURE(pInsertAtomCommalist->count() > 0,"OResultSet: pInsertAtomCommalist <= 0"); |
539 | |
|
540 | 0 | sal_Int32 nIndex=0; |
541 | 0 | for (size_t i = 0; i < pInsertAtomCommalist->count(); i++) |
542 | 0 | { |
543 | 0 | OSQLParseNode * pRow_Value_Const = pInsertAtomCommalist->getChild(i); // row_value_constructor |
544 | 0 | OSL_ENSURE(pRow_Value_Const != nullptr,"OResultSet: pRow_Value_Const must not be NULL!"); |
545 | 0 | if(SQL_ISRULE(pRow_Value_Const,parameter)) |
546 | 0 | { |
547 | 0 | ParseAssignValues(aColumnNameList,pRow_Value_Const,nIndex++); // only one Columnname allowed per loop |
548 | 0 | } |
549 | 0 | else if(pRow_Value_Const->isToken()) |
550 | 0 | ParseAssignValues(aColumnNameList,pRow_Value_Const,i); |
551 | 0 | else |
552 | 0 | { |
553 | 0 | if(pRow_Value_Const->count() == aColumnNameList.size()) |
554 | 0 | { |
555 | 0 | for (size_t j = 0; j < pRow_Value_Const->count(); ++j) |
556 | 0 | ParseAssignValues(aColumnNameList,pRow_Value_Const->getChild(j),nIndex++); |
557 | 0 | } |
558 | 0 | else |
559 | 0 | throwFunctionSequenceException(*this); |
560 | 0 | } |
561 | 0 | } |
562 | 0 | } |
563 | 0 | else if (SQL_ISRULE(m_pParseTree,update_statement_searched)) |
564 | 0 | { |
565 | 0 | if(m_aAssignValues.is()) |
566 | 0 | m_aAssignValues->clear(); |
567 | 0 | sal_Int32 nCount = Reference<XIndexAccess>(m_xColNames,UNO_QUERY_THROW)->getCount(); |
568 | 0 | m_aAssignValues = new OAssignValues(nCount); |
569 | | // unbound all |
570 | 0 | std::for_each(m_aAssignValues->begin()+1,m_aAssignValues->end(),TSetRefBound(false)); |
571 | |
|
572 | 0 | m_aParameterIndexes.resize(nCount+1,SQL_NO_PARAMETER); |
573 | |
|
574 | 0 | OSL_ENSURE(m_pParseTree->count() >= 4,"OResultSet: Error in Parse Tree"); |
575 | |
|
576 | 0 | OSQLParseNode * pAssignmentCommalist = m_pParseTree->getChild(3); |
577 | 0 | assert(pAssignmentCommalist && "OResultSet: pAssignmentCommalist == NULL"); |
578 | 0 | OSL_ENSURE(SQL_ISRULE(pAssignmentCommalist,assignment_commalist),"OResultSet: Error in Parse Tree"); |
579 | 0 | OSL_ENSURE(pAssignmentCommalist->count() > 0,"OResultSet: pAssignmentCommalist->count() <= 0"); |
580 | | |
581 | | // work on all assignments (commalist) ... |
582 | 0 | std::vector< OUString> aList(1); |
583 | 0 | for (size_t i = 0; i < pAssignmentCommalist->count(); i++) |
584 | 0 | { |
585 | 0 | OSQLParseNode * pAssignment = pAssignmentCommalist->getChild(i); |
586 | 0 | assert(pAssignment && "OResultSet: pAssignment == NULL"); |
587 | 0 | OSL_ENSURE(SQL_ISRULE(pAssignment,assignment),"OResultSet: Error in Parse Tree"); |
588 | 0 | OSL_ENSURE(pAssignment->count() == 3,"OResultSet: pAssignment->count() != 3"); |
589 | |
|
590 | 0 | OSQLParseNode * pCol = pAssignment->getChild(0); |
591 | 0 | assert(pCol && "OResultSet: pCol == NULL"); |
592 | |
|
593 | 0 | OSQLParseNode * pComp = pAssignment->getChild(1); |
594 | 0 | assert(pComp && "OResultSet: pComp == NULL"); |
595 | 0 | OSL_ENSURE(pComp->getNodeType() == SQLNodeType::Equal,"OResultSet: pComp->getNodeType() != SQLNodeType::Comparison"); |
596 | 0 | if (pComp->getTokenValue().toChar() != '=') |
597 | 0 | { |
598 | 0 | throwFunctionSequenceException(*this); |
599 | 0 | } |
600 | |
|
601 | 0 | OSQLParseNode * pVal = pAssignment->getChild(2); |
602 | 0 | OSL_ENSURE(pVal != nullptr,"OResultSet: pVal == NULL"); |
603 | 0 | aList[0] = pCol->getTokenValue(); |
604 | 0 | ParseAssignValues(aList,pVal,0); |
605 | 0 | } |
606 | |
|
607 | 0 | } |
608 | 19.3k | } |
609 | | |
610 | | void OStatement_Base::ParseAssignValues(const std::vector< OUString>& aColumnNameList,OSQLParseNode* pRow_Value_Constructor_Elem, sal_Int32 nIndex) |
611 | 0 | { |
612 | 0 | OSL_ENSURE(o3tl::make_unsigned(nIndex) <= aColumnNameList.size(),"SdbFileCursor::ParseAssignValues: nIndex > aColumnNameList.GetTokenCount()"); |
613 | 0 | const OUString& aColumnName(aColumnNameList[nIndex]); |
614 | 0 | OSL_ENSURE(aColumnName.getLength() > 0,"OResultSet: Column-Name not found"); |
615 | 0 | assert(pRow_Value_Constructor_Elem != nullptr && "OResultSet: pRow_Value_Constructor_Elem must not be NULL!"); |
616 | |
|
617 | 0 | if (pRow_Value_Constructor_Elem->getNodeType() == SQLNodeType::String || |
618 | 0 | pRow_Value_Constructor_Elem->getNodeType() == SQLNodeType::IntNum || |
619 | 0 | pRow_Value_Constructor_Elem->getNodeType() == SQLNodeType::ApproxNum) |
620 | 0 | { |
621 | | // set value: |
622 | 0 | SetAssignValue(aColumnName, pRow_Value_Constructor_Elem->getTokenValue()); |
623 | 0 | } |
624 | 0 | else if (SQL_ISTOKEN(pRow_Value_Constructor_Elem,NULL)) |
625 | 0 | { |
626 | | // set NULL |
627 | 0 | SetAssignValue(aColumnName, OUString(), true); |
628 | 0 | } |
629 | 0 | else if (SQL_ISRULE(pRow_Value_Constructor_Elem,parameter)) |
630 | 0 | parseParamterElem(aColumnName,pRow_Value_Constructor_Elem); |
631 | 0 | else |
632 | 0 | { |
633 | 0 | throwFunctionSequenceException(*this); |
634 | 0 | } |
635 | 0 | } |
636 | | |
637 | | void OStatement_Base::SetAssignValue(const OUString& aColumnName, |
638 | | const OUString& aValue, |
639 | | bool bSetNull, |
640 | | sal_uInt32 nParameter) |
641 | 0 | { |
642 | 0 | Reference<XPropertySet> xCol; |
643 | 0 | m_xColNames->getByName(aColumnName) >>= xCol; |
644 | 0 | sal_Int32 nId = Reference<XColumnLocate>(m_xColNames,UNO_QUERY_THROW)->findColumn(aColumnName); |
645 | | // does this column actually exist in the file? |
646 | |
|
647 | 0 | if (!xCol.is()) |
648 | 0 | { |
649 | | // This Column doesn't exist! |
650 | 0 | throwFunctionSequenceException(*this); |
651 | 0 | } |
652 | | |
653 | | |
654 | | // Everything tested and we have the names of the Column. |
655 | | // Now allocate one Value, set the value and tie the value to the Row. |
656 | 0 | if (bSetNull) |
657 | 0 | (*m_aAssignValues)[nId]->setNull(); |
658 | 0 | else |
659 | 0 | { |
660 | 0 | switch (::comphelper::getINT32(xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)))) |
661 | 0 | { |
662 | 0 | case DataType::BIT: |
663 | 0 | if (aValue.equalsIgnoreAsciiCase("TRUE") || aValue[0] == '1') |
664 | 0 | *(*m_aAssignValues)[nId] = true; |
665 | 0 | else if (aValue.equalsIgnoreAsciiCase("FALSE") || aValue[0] == '0') |
666 | 0 | *(*m_aAssignValues)[nId] = false; |
667 | 0 | else |
668 | 0 | throwFunctionSequenceException(*this); |
669 | 0 | break; |
670 | 0 | case DataType::CHAR: |
671 | 0 | case DataType::VARCHAR: |
672 | 0 | case DataType::LONGVARCHAR: |
673 | | //Characterset is already converted, since the entire statement was converted |
674 | 0 | case DataType::TINYINT: |
675 | 0 | case DataType::SMALLINT: |
676 | 0 | case DataType::INTEGER: |
677 | 0 | case DataType::DECIMAL: |
678 | 0 | case DataType::NUMERIC: |
679 | 0 | case DataType::REAL: |
680 | 0 | case DataType::DOUBLE: |
681 | 0 | case DataType::DATE: |
682 | 0 | case DataType::TIME: |
683 | 0 | case DataType::TIMESTAMP: |
684 | 0 | *(*m_aAssignValues)[nId] = ORowSetValue(aValue); |
685 | 0 | break; |
686 | 0 | default: |
687 | 0 | throwFunctionSequenceException(*this); |
688 | 0 | } |
689 | 0 | } |
690 | | |
691 | | // save Parameter-No. (as User Data) |
692 | | // SQL_NO_PARAMETER = no Parameter. |
693 | 0 | m_aAssignValues->setParameterIndex(nId,nParameter); |
694 | 0 | if(nParameter != SQL_NO_PARAMETER) |
695 | 0 | m_aParameterIndexes[nParameter] = nId; |
696 | 0 | } |
697 | | |
698 | | void OStatement_Base::parseParamterElem(const OUString& /*_sColumnName*/,OSQLParseNode* /*pRow_Value_Constructor_Elem*/) |
699 | 0 | { |
700 | | // do nothing here |
701 | 0 | } |
702 | | |
703 | | }// namespace |
704 | | |
705 | | |
706 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |