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