build fix
[LibreOffice.git] / connectivity / source / drivers / file / FPreparedStatement.cxx
blobc59496af98f2d192916d2fdbc0726f771e75bea3
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 <connectivity/sdbcx/VColumn.hxx>
22 #include <osl/diagnose.h>
23 #include "file/FPreparedStatement.hxx"
24 #include <com/sun/star/sdbc/DataType.hpp>
25 #include "file/FResultSetMetaData.hxx"
26 #include <cppuhelper/queryinterface.hxx>
27 #include <cppuhelper/typeprovider.hxx>
28 #include <comphelper/sequence.hxx>
29 #include <com/sun/star/lang/DisposedException.hpp>
30 #include <connectivity/dbconversion.hxx>
31 #include <connectivity/dbexception.hxx>
32 #include <connectivity/dbtools.hxx>
33 #include <connectivity/PColumn.hxx>
34 #include <comphelper/types.hxx>
35 #include <com/sun/star/sdbc/ColumnValue.hpp>
36 #include "resource/file_res.hrc"
38 using namespace connectivity;
39 using namespace comphelper;
40 using namespace ::dbtools;
41 using namespace connectivity::file;
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;
50 IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbc.driver.file.PreparedStatement","com.sun.star.sdbc.PreparedStatement");
52 OPreparedStatement::OPreparedStatement( OConnection* _pConnection)
53 : OStatement_BASE2( _pConnection )
58 OPreparedStatement::~OPreparedStatement()
63 void OPreparedStatement::disposing()
65 ::osl::MutexGuard aGuard(m_aMutex);
67 OStatement_BASE2::disposing();
69 m_xParamColumns = nullptr;
70 m_xMetaData.clear();
71 if(m_aParameterRow.is())
73 m_aParameterRow->get().clear();
74 m_aParameterRow = nullptr;
78 void OPreparedStatement::construct(const OUString& sql) throw(SQLException, RuntimeException, std::exception)
80 OStatement_Base::construct(sql);
82 m_aParameterRow = new OValueRefVector();
83 m_aParameterRow->get().push_back(new ORowSetValueDecorator(sal_Int32(0)) );
85 Reference<XIndexAccess> xNames(m_xColNames,UNO_QUERY);
87 if ( m_aSQLIterator.getStatementType() == OSQLStatementType::Select )
88 m_xParamColumns = m_aSQLIterator.getParameters();
89 else
91 m_xParamColumns = new OSQLColumns();
92 // describe all parameters need for the resultset
93 describeParameter();
96 OValueRefRow aTemp;
97 OResultSet::setBoundedColumns(m_aEvaluateRow,aTemp,m_xParamColumns,xNames,false,m_xDBMetaData,m_aColMapping);
100 rtl::Reference<OResultSet> OPreparedStatement::makeResultSet()
102 closeResultSet();
104 rtl::Reference<OResultSet> xResultSet(createResultSet());
105 m_xResultSet = xResultSet.get();
106 initializeResultSet(xResultSet.get());
107 initResultSet(xResultSet.get());
108 return xResultSet;
111 Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException, std::exception)
113 Any aRet = OStatement_BASE2::queryInterface(rType);
114 return aRet.hasValue() ? aRet : ::cppu::queryInterface( rType,
115 static_cast< XPreparedStatement*>(this),
116 static_cast< XParameters*>(this),
117 static_cast< XResultSetMetaDataSupplier*>(this));
120 css::uno::Sequence< css::uno::Type > SAL_CALL OPreparedStatement::getTypes( ) throw(css::uno::RuntimeException, std::exception)
122 ::cppu::OTypeCollection aTypes( cppu::UnoType<XPreparedStatement>::get(),
123 cppu::UnoType<XParameters>::get(),
124 cppu::UnoType<XResultSetMetaDataSupplier>::get());
126 return ::comphelper::concatSequences(aTypes.getTypes(),OStatement_BASE2::getTypes());
130 Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( ) throw(SQLException, RuntimeException, std::exception)
132 ::osl::MutexGuard aGuard( m_aMutex );
133 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
136 if(!m_xMetaData.is())
137 m_xMetaData = new OResultSetMetaData(m_aSQLIterator.getSelectColumns(),m_aSQLIterator.getTables().begin()->first,m_pTable.get());
138 return m_xMetaData.get();
142 void SAL_CALL OPreparedStatement::close( ) throw(SQLException, RuntimeException, std::exception)
144 ::osl::MutexGuard aGuard( m_aMutex );
145 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
147 closeResultSet();
151 sal_Bool SAL_CALL OPreparedStatement::execute( ) throw(SQLException, RuntimeException, std::exception)
153 ::osl::MutexGuard aGuard( m_aMutex );
154 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
156 rtl::Reference<OResultSet> xRS(makeResultSet());
157 // since we don't support the XMultipleResults interface, nobody will ever get that ResultSet...
158 if(xRS.is())
159 xRS->dispose();
161 return m_aSQLIterator.getStatementType() == OSQLStatementType::Select;
165 sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( ) throw(SQLException, RuntimeException, std::exception)
167 ::osl::MutexGuard aGuard( m_aMutex );
168 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
170 rtl::Reference<OResultSet> xRS(makeResultSet());
171 if(xRS.is())
173 const sal_Int32 res(xRS->getRowCountResult());
174 // nobody will ever get that ResultSet...
175 xRS->dispose();
176 return res;
178 else
179 return 0;
183 void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const OUString& x ) throw(SQLException, RuntimeException, std::exception)
185 setParameter(parameterIndex,x);
189 Reference< XConnection > SAL_CALL OPreparedStatement::getConnection( ) throw(SQLException, RuntimeException, std::exception)
191 ::osl::MutexGuard aGuard( m_aMutex );
192 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
194 return Reference< XConnection >(m_pConnection.get());
198 Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( ) throw(SQLException, RuntimeException, std::exception)
200 ::osl::MutexGuard aGuard( m_aMutex );
201 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
203 return makeResultSet().get();
207 void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException, std::exception)
209 setParameter(parameterIndex,static_cast<bool>(x));
212 void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException, std::exception)
214 setParameter(parameterIndex,x);
218 void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const util::Date& aData ) throw(SQLException, RuntimeException, std::exception)
220 setParameter(parameterIndex,DBTypeConversion::toDouble(aData));
223 void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const util::Time& aVal ) throw(SQLException, RuntimeException, std::exception)
225 setParameter(parameterIndex,DBTypeConversion::toDouble(aVal));
229 void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const util::DateTime& aVal ) throw(SQLException, RuntimeException, std::exception)
231 setParameter(parameterIndex,DBTypeConversion::toDouble(aVal));
235 void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException, std::exception)
237 setParameter(parameterIndex,x);
241 void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException, std::exception)
243 setParameter(parameterIndex,x);
247 void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException, std::exception)
249 setParameter(parameterIndex,x);
253 void SAL_CALL OPreparedStatement::setLong( sal_Int32 /*parameterIndex*/, sal_Int64 /*aVal*/ ) throw(SQLException, RuntimeException, std::exception)
255 throwFeatureNotImplementedSQLException( "XParameters::setLong", *this );
259 void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ ) throw(SQLException, RuntimeException, std::exception)
261 ::osl::MutexGuard aGuard( m_aMutex );
262 checkAndResizeParameters(parameterIndex);
264 if ( m_aAssignValues.is() )
265 (m_aAssignValues->get())[m_aParameterIndexes[parameterIndex]]->setNull();
266 else
267 (m_aParameterRow->get())[parameterIndex]->setNull();
271 void SAL_CALL OPreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ ) throw(SQLException, RuntimeException, std::exception)
273 throwFeatureNotImplementedSQLException( "XParameters::setClob", *this );
277 void SAL_CALL OPreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ ) throw(SQLException, RuntimeException, std::exception)
279 throwFeatureNotImplementedSQLException( "XParameters::setBlob", *this );
283 void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException, std::exception)
285 throwFeatureNotImplementedSQLException( "XParameters::setArray", *this );
289 void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException, std::exception)
291 throwFeatureNotImplementedSQLException( "XParameters::setRef", *this );
295 void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException, std::exception)
297 switch(sqlType)
299 case DataType::DECIMAL:
300 case DataType::NUMERIC:
301 setString(parameterIndex,::comphelper::getString(x));
302 break;
303 default:
304 ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
305 break;
310 void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& /*typeName*/ ) throw(SQLException, RuntimeException, std::exception)
312 setNull(parameterIndex,sqlType);
316 void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException, std::exception)
318 if(!::dbtools::implSetObject(this,parameterIndex,x))
320 const OUString sError( m_pConnection->getResources().getResourceStringWithSubstitution(
321 STR_UNKNOWN_PARA_TYPE,
322 "$position$", OUString::number(parameterIndex)
323 ) );
324 ::dbtools::throwGenericSQLException(sError,*this);
326 // setObject (parameterIndex, x, sqlType, 0);
330 void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException, std::exception)
332 setParameter(parameterIndex,x);
336 void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException, std::exception)
338 setParameter(parameterIndex,x);
342 void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException, std::exception)
344 setBinaryStream(parameterIndex,x,length );
348 void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException, std::exception)
350 if(!x.is())
351 ::dbtools::throwFunctionSequenceException(*this);
353 Sequence<sal_Int8> aSeq;
354 x->readBytes(aSeq,length);
355 setParameter(parameterIndex,aSeq);
359 void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException, std::exception)
361 ::osl::MutexGuard aGuard( m_aMutex );
362 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
364 m_aParameterRow->get().clear();
365 m_aParameterRow->get().push_back(new ORowSetValueDecorator(sal_Int32(0)) );
368 OResultSet* OPreparedStatement::createResultSet()
370 return new OResultSet(this,m_aSQLIterator);
373 void OPreparedStatement::initResultSet(OResultSet *pResultSet)
375 // check if we got enough parameters
376 if ( (m_aParameterRow.is() && ( m_aParameterRow->get().size() -1 ) < m_xParamColumns->get().size()) ||
377 (m_xParamColumns.is() && !m_aParameterRow.is() && !m_aParameterRow->get().empty()) )
378 m_pConnection->throwGenericSQLException(STR_INVALID_PARA_COUNT,*this);
380 pResultSet->OpenImpl();
381 pResultSet->setMetaData(getMetaData());
384 void SAL_CALL OPreparedStatement::acquire() throw()
386 OStatement_BASE2::acquire();
389 void SAL_CALL OPreparedStatement::release() throw()
391 OStatement_BASE2::release();
394 void OPreparedStatement::checkAndResizeParameters(sal_Int32 parameterIndex)
396 ::connectivity::checkDisposed(OStatement_BASE::rBHelper.bDisposed);
397 if ( m_aAssignValues.is() && (parameterIndex < 1 || parameterIndex >= static_cast<sal_Int32>(m_aParameterIndexes.size())) )
398 throwInvalidIndexException(*this);
399 else if ( static_cast<sal_Int32>((m_aParameterRow->get()).size()) <= parameterIndex )
401 sal_Int32 i = m_aParameterRow->get().size();
402 (m_aParameterRow->get()).resize(parameterIndex+1);
403 for ( ; i <= parameterIndex; ++i)
405 if ( !(m_aParameterRow->get())[i].is() )
406 (m_aParameterRow->get())[i] = new ORowSetValueDecorator;
411 void OPreparedStatement::setParameter(sal_Int32 parameterIndex, const ORowSetValue& x)
413 ::osl::MutexGuard aGuard( m_aMutex );
414 checkAndResizeParameters(parameterIndex);
416 if(m_aAssignValues.is())
417 *(m_aAssignValues->get())[m_aParameterIndexes[parameterIndex]] = x;
418 else
419 *((m_aParameterRow->get())[parameterIndex]) = x;
422 sal_uInt32 OPreparedStatement::AddParameter(OSQLParseNode * pParameter, const Reference<XPropertySet>& _xCol)
424 OSL_ENSURE(SQL_ISRULE(pParameter,parameter),"OResultSet::AddParameter: Argument ist kein Parameter");
425 OSL_ENSURE(pParameter->count() > 0,"OResultSet: Fehler im Parse Tree");
427 OUString sParameterName;
428 // set up Parameter-Column:
429 sal_Int32 eType = DataType::VARCHAR;
430 sal_uInt32 nPrecision = 255;
431 sal_Int32 nScale = 0;
432 sal_Int32 nNullable = ColumnValue::NULLABLE;
434 if (_xCol.is())
436 // Use type, precision, scale ... from the given column,
437 // because this Column will get a value assigned or
438 // with this Column the value will be compared.
439 _xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= eType;
440 _xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)) >>= nPrecision;
441 _xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)) >>= nScale;
442 _xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE)) >>= nNullable;
443 _xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= sParameterName;
446 Reference<XPropertySet> xParaColumn = new connectivity::parse::OParseColumn(sParameterName
447 ,OUString()
448 ,OUString()
449 ,OUString()
450 ,nNullable
451 ,nPrecision
452 ,nScale
453 ,eType
454 ,false
455 ,false
456 ,m_aSQLIterator.isCaseSensitive()
457 ,OUString()
458 ,OUString()
459 ,OUString());
460 m_xParamColumns->get().push_back(xParaColumn);
461 return m_xParamColumns->get().size();
464 void OPreparedStatement::describeColumn(OSQLParseNode* _pParameter,OSQLParseNode* _pNode,const OSQLTable& _xTable)
466 Reference<XPropertySet> xProp;
467 if(SQL_ISRULE(_pNode,column_ref))
469 OUString sColumnName,sTableRange;
470 m_aSQLIterator.getColumnRange(_pNode,sColumnName,sTableRange);
471 if ( !sColumnName.isEmpty() )
473 Reference<XNameAccess> xNameAccess = _xTable->getColumns();
474 if(xNameAccess->hasByName(sColumnName))
475 xNameAccess->getByName(sColumnName) >>= xProp;
476 AddParameter(_pParameter,xProp);
479 // else
480 // AddParameter(_pParameter,xProp);
483 void OPreparedStatement::describeParameter()
485 ::std::vector< OSQLParseNode*> aParseNodes;
486 scanParameter(m_pParseTree,aParseNodes);
487 if ( !aParseNodes.empty() )
489 // m_xParamColumns = new OSQLColumns();
490 const OSQLTables& rTabs = m_aSQLIterator.getTables();
491 if( !rTabs.empty() )
493 OSQLTable xTable = rTabs.begin()->second;
494 ::std::vector< OSQLParseNode*>::const_iterator aIter = aParseNodes.begin();
495 for (;aIter != aParseNodes.end();++aIter )
497 describeColumn(*aIter,(*aIter)->getParent()->getChild(0),xTable);
502 void OPreparedStatement::initializeResultSet(OResultSet* pRS)
504 OStatement_Base::initializeResultSet(pRS);
506 pRS->setParameterColumns(m_xParamColumns);
507 pRS->setParameterRow(m_aParameterRow);
509 // Substitute parameter (AssignValues and criteria):
510 if (!m_xParamColumns->get().empty())
512 // begin with AssignValues
513 sal_uInt16 nParaCount=0; // gives the current number of previously set Parameters
515 // search for parameters to be substituted:
516 size_t nCount = m_aAssignValues.is() ? m_aAssignValues->get().size() : 1; // 1 is important for the Criteria
517 for (size_t j = 1; j < nCount; j++)
519 sal_uInt32 nParameter = (*m_aAssignValues).getParameterIndex(j);
520 if (nParameter == SQL_NO_PARAMETER)
521 continue; // this AssignValue is no Parameter
523 ++nParaCount; // now the Parameter is valid
526 if (m_aParameterRow.is() && (m_xParamColumns->get().size()+1) != m_aParameterRow->get().size() )
528 sal_Int32 i = m_aParameterRow->get().size();
529 sal_Int32 nParamColumns = m_xParamColumns->get().size()+1;
530 m_aParameterRow->get().resize(nParamColumns);
531 for ( ;i < nParamColumns; ++i )
533 if ( !(m_aParameterRow->get())[i].is() )
534 (m_aParameterRow->get())[i] = new ORowSetValueDecorator;
537 if (m_aParameterRow.is() && nParaCount < m_aParameterRow->get().size() )
538 m_pSQLAnalyzer->bindParameterRow(m_aParameterRow);
542 void OPreparedStatement::parseParamterElem(const OUString& _sColumnName, OSQLParseNode* pRow_Value_Constructor_Elem)
544 Reference<XPropertySet> xCol;
545 m_xColNames->getByName(_sColumnName) >>= xCol;
546 sal_Int32 nParameter = -1;
547 if(m_xParamColumns.is())
549 OSQLColumns::Vector::const_iterator aIter = find(m_xParamColumns->get().begin(),m_xParamColumns->get().end(),_sColumnName,::comphelper::UStringMixEqual(m_pTable->isCaseSensitive()));
550 if(aIter != m_xParamColumns->get().end())
551 nParameter = m_xParamColumns->get().size() - (m_xParamColumns->get().end() - aIter) + 1;// +1 because the rows start at 1
553 if(nParameter == -1)
554 nParameter = AddParameter(pRow_Value_Constructor_Elem,xCol);
555 // Save number of parameter in the variable:
556 SetAssignValue(_sColumnName, OUString(), true, nParameter);
560 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */