Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / connectivity / source / drivers / mozab / MPreparedStatement.cxx
blobe8ace7cf11ce7bc4e5efbfb0532ed5083004028e
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 .
20 #include <stdio.h>
21 #include <osl/diagnose.h>
22 #include "connectivity/sdbcx/VColumn.hxx"
23 #include "MPreparedStatement.hxx"
24 #include <com/sun/star/sdbc/DataType.hpp>
25 #include "MResultSetMetaData.hxx"
26 #include <cppuhelper/typeprovider.hxx>
27 #include <comphelper/sequence.hxx>
28 #include <com/sun/star/lang/DisposedException.hpp>
29 #include "connectivity/dbexception.hxx"
30 #include "connectivity/dbtools.hxx"
31 #include <comphelper/types.hxx>
32 #include <com/sun/star/sdbc/ColumnValue.hpp>
33 #include "diagnose_ex.h"
35 #if OSL_DEBUG_LEVEL > 0
36 # define OUtoCStr( x ) ( OUStringToOString ( (x), RTL_TEXTENCODING_ASCII_US).getStr())
37 #else /* OSL_DEBUG_LEVEL */
38 # define OUtoCStr( x ) ("dummy")
39 #endif /* OSL_DEBUG_LEVEL */
41 using namespace ::comphelper;
42 using namespace connectivity;
43 using namespace connectivity::mozab;
44 using namespace com::sun::star::uno;
45 using namespace com::sun::star::lang;
46 using namespace com::sun::star::beans;
47 using namespace com::sun::star::sdbc;
48 using namespace com::sun::star::sdbcx;
49 using namespace com::sun::star::container;
50 using namespace com::sun::star::io;
51 using namespace com::sun::star::util;
53 IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.mozab.PreparedStatement","com.sun.star.sdbc.PreparedStatement");
56 OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const OUString& sql)
57 :OCommonStatement(_pConnection)
58 ,m_nNumParams(0)
59 ,m_sSqlStatement(sql)
60 ,m_bPrepared(sal_False)
61 ,m_pResultSet()
65 OPreparedStatement::~OPreparedStatement()
69 void OPreparedStatement::lateInit()
71 if ( eSelect != parseSql( m_sSqlStatement ) )
72 throw SQLException();
75 void SAL_CALL OPreparedStatement::disposing()
77 ::osl::MutexGuard aGuard(m_aMutex);
79 OCommonStatement::disposing();
81 m_xMetaData.clear();
82 if(m_aParameterRow.is())
84 m_aParameterRow->get().clear();
85 m_aParameterRow = NULL;
87 m_xParamColumns = NULL;
91 OCommonStatement::StatementType OPreparedStatement::parseSql( const OUString& sql , sal_Bool bAdjusted )
92 throw ( ::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException )
94 StatementType eStatementType = OCommonStatement::parseSql( sql, bAdjusted );
95 if ( eStatementType != eSelect )
96 return eStatementType;
98 m_xParamColumns = new OSQLColumns();
100 // describe all parameters need for the resultset
101 describeParameter();
103 Reference<XIndexAccess> xNames(m_xColNames,UNO_QUERY);
104 OResultSet::setBoundedColumns( m_aRow, m_xParamColumns, xNames, sal_False, m_xDBMetaData, m_aColMapping );
106 return eStatementType;
110 void OPreparedStatement::initializeResultSet( OResultSet* _pResult )
112 OCommonStatement::initializeResultSet( _pResult );
113 _pResult->setParameterColumns( m_xParamColumns );
114 _pResult->setParameterRow( m_aParameterRow );
118 void OPreparedStatement::clearCachedResultSet()
120 OCommonStatement::clearCachedResultSet();
121 m_pResultSet.clear();
122 m_xMetaData.clear();
125 void OPreparedStatement::cacheResultSet( const ::rtl::Reference< OResultSet >& _pResult )
127 OCommonStatement::cacheResultSet( _pResult );
128 OSL_PRECOND( m_pResultSet == NULL, "OPreparedStatement::parseSql: you should call clearCachedResultSet before!" );
129 m_pResultSet = _pResult;
133 void SAL_CALL OPreparedStatement::acquire() throw()
135 OCommonStatement::acquire();
138 void SAL_CALL OPreparedStatement::release() throw()
140 OCommonStatement::release();
143 Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException)
145 Any aRet = OCommonStatement::queryInterface(rType);
146 if(!aRet.hasValue())
147 aRet = OPreparedStatement_BASE::queryInterface(rType);
148 return aRet;
151 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException)
153 return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OCommonStatement::getTypes());
157 Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( ) throw(SQLException, RuntimeException)
159 ::osl::MutexGuard aGuard( m_aMutex );
160 checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
162 sal_Bool bReadOnly = sal_True;
163 if ( m_pResultSet.is() )
164 bReadOnly = m_pResultSet->determineReadOnly();
165 // if we do not have a result set, then we have not been executed, yet. In this case, assuming readonly=true is
166 // okay, /me thinks.
168 if ( !m_xMetaData.is() )
169 m_xMetaData = new OResultSetMetaData( m_pSQLIterator->getSelectColumns(), m_pSQLIterator->getTables().begin()->first ,m_pTable,bReadOnly );
171 return m_xMetaData;
175 sal_Bool SAL_CALL OPreparedStatement::execute( ) throw(SQLException, RuntimeException)
177 ::osl::MutexGuard aGuard( m_aMutex );
178 checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
180 Reference< XResultSet> xResult = executeQuery();
181 return xResult.is();
185 sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( ) throw(SQLException, RuntimeException)
187 ::dbtools::throwFeatureNotImplementedException( "XStatement::executeUpdate", *this );
188 return 0;
192 void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const OUString& x ) throw(SQLException, RuntimeException)
194 ::osl::MutexGuard aGuard( m_aMutex );
195 checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
197 OSL_TRACE("prepStmt::setString( %s )", OUtoCStr( x ) );
198 setParameter( parameterIndex, x );
202 Reference< XConnection > SAL_CALL OPreparedStatement::getConnection( ) throw(SQLException, RuntimeException)
204 ::osl::MutexGuard aGuard( m_aMutex );
205 checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
207 return (Reference< XConnection >)m_pConnection;
211 Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( ) throw(SQLException, RuntimeException)
213 ::osl::MutexGuard aGuard( m_aMutex );
214 OSL_TRACE("In: OPreparedStatement::executeQuery" );
215 checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
217 // our statement has already been parsed in lateInit, no need to do all this (potentially expensive)
218 // stuff again. Just execute.
219 return impl_executeCurrentQuery();
223 void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 /*parameterIndex*/, sal_Bool /*x*/ ) throw(SQLException, RuntimeException)
225 ::dbtools::throwFeatureNotImplementedException( "XParameters::setBoolean", *this );
228 void SAL_CALL OPreparedStatement::setByte( sal_Int32 /*parameterIndex*/, sal_Int8 /*x*/ ) throw(SQLException, RuntimeException)
230 ::dbtools::throwFeatureNotImplementedException( "XParameters::setByte", *this );
234 void SAL_CALL OPreparedStatement::setDate( sal_Int32 /*parameterIndex*/, const Date& /*aData*/ ) throw(SQLException, RuntimeException)
236 ::dbtools::throwFeatureNotImplementedException( "XParameters::setDate", *this );
241 void SAL_CALL OPreparedStatement::setTime( sal_Int32 /*parameterIndex*/, const Time& /*aVal*/ ) throw(SQLException, RuntimeException)
243 ::dbtools::throwFeatureNotImplementedException( "XParameters::setTime", *this );
247 void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 /*parameterIndex*/, const DateTime& /*aVal*/ ) throw(SQLException, RuntimeException)
249 ::dbtools::throwFeatureNotImplementedException( "XParameters::setTimestamp", *this );
253 void SAL_CALL OPreparedStatement::setDouble( sal_Int32 /*parameterIndex*/, double /*x*/ ) throw(SQLException, RuntimeException)
255 ::dbtools::throwFeatureNotImplementedException( "XParameters::setDouble", *this );
260 void SAL_CALL OPreparedStatement::setFloat( sal_Int32 /*parameterIndex*/, float /*x*/ ) throw(SQLException, RuntimeException)
262 ::dbtools::throwFeatureNotImplementedException( "XParameters::setFloat", *this );
266 void SAL_CALL OPreparedStatement::setInt( sal_Int32 /*parameterIndex*/, sal_Int32 /*x*/ ) throw(SQLException, RuntimeException)
268 ::dbtools::throwFeatureNotImplementedException( "XParameters::setInt", *this );
272 void SAL_CALL OPreparedStatement::setLong( sal_Int32 /*parameterIndex*/, sal_Int64 /*aVal*/ ) throw(SQLException, RuntimeException)
274 ::dbtools::throwFeatureNotImplementedException( "XParameters::setLong", *this );
278 void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ ) throw(SQLException, RuntimeException)
280 ::osl::MutexGuard aGuard( m_aMutex );
281 checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
283 checkAndResizeParameters(parameterIndex);
285 (m_aParameterRow->get())[parameterIndex].setNull();
289 void SAL_CALL OPreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ ) throw(SQLException, RuntimeException)
291 ::dbtools::throwFeatureNotImplementedException( "XParameters::setClob", *this );
295 void SAL_CALL OPreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ ) throw(SQLException, RuntimeException)
297 ::dbtools::throwFeatureNotImplementedException( "XParameters::setBlob", *this );
301 void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException)
303 ::dbtools::throwFeatureNotImplementedException( "XParameters::setArray", *this );
307 void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException)
309 ::dbtools::throwFeatureNotImplementedException( "XParameters::setRef", *this );
313 void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 /*parameterIndex*/, const Any& /*x*/, sal_Int32 /*sqlType*/, sal_Int32 /*scale*/ ) throw(SQLException, RuntimeException)
315 ::dbtools::throwFeatureNotImplementedException( "XParameters::setObjectWithInfo", *this );
319 void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& /*typeName*/ ) throw(SQLException, RuntimeException)
321 setNull(parameterIndex,sqlType);
325 void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException)
327 ::dbtools::implSetObject(this,parameterIndex,x);
331 void SAL_CALL OPreparedStatement::setShort( sal_Int32 /*parameterIndex*/, sal_Int16 /*x*/ ) throw(SQLException, RuntimeException)
333 ::dbtools::throwFeatureNotImplementedException( "XParameters::setShort", *this );
337 void SAL_CALL OPreparedStatement::setBytes( sal_Int32 /*parameterIndex*/, const Sequence< sal_Int8 >& /*x*/ ) throw(SQLException, RuntimeException)
339 ::dbtools::throwFeatureNotImplementedException( "XParameters::setBytes", *this );
344 void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 /*parameterIndex*/, const Reference< ::com::sun::star::io::XInputStream >& /*x*/, sal_Int32 /*length*/ ) throw(SQLException, RuntimeException)
346 ::dbtools::throwFeatureNotImplementedException( "XParameters::setCharacterStream", *this );
350 void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 /*parameterIndex*/, const Reference< ::com::sun::star::io::XInputStream >& /*x*/, sal_Int32 /*length*/ ) throw(SQLException, RuntimeException)
352 ::dbtools::throwFeatureNotImplementedException( "XParameters::setBinaryStream", *this );
356 void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException)
360 void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception)
362 switch(nHandle)
364 case PROPERTY_ID_RESULTSETCONCURRENCY:
365 break;
366 case PROPERTY_ID_RESULTSETTYPE:
367 break;
368 case PROPERTY_ID_FETCHDIRECTION:
369 break;
370 case PROPERTY_ID_USEBOOKMARKS:
371 break;
372 default:
373 OCommonStatement::setFastPropertyValue_NoBroadcast(nHandle,rValue);
378 void OPreparedStatement::checkAndResizeParameters(sal_Int32 parameterIndex)
380 ::connectivity::checkDisposed(OCommonStatement_IBASE::rBHelper.bDisposed);
382 if ( !m_aParameterRow.is() ) {
383 m_aParameterRow = new OValueVector();
384 m_aParameterRow->get().push_back(sal_Int32(0));
387 if ((sal_Int32)(m_aParameterRow->get()).size() <= parameterIndex)
388 (m_aParameterRow->get()).resize(parameterIndex+1);
391 void OPreparedStatement::setParameter(sal_Int32 parameterIndex, const
392 ORowSetValue& x)
394 ::osl::MutexGuard aGuard( m_aMutex );
395 checkAndResizeParameters(parameterIndex);
397 OSL_TRACE("setParameter( %d, '%s')", parameterIndex, OUtoCStr(x) );
398 (m_aParameterRow->get())[parameterIndex] = x;
402 size_t OPreparedStatement::AddParameter(OSQLParseNode * pParameter, const Reference<XPropertySet>& _xCol)
404 OSL_UNUSED( pParameter );
405 // Count of the newly added Parameters
406 size_t nParameter = m_xParamColumns->get().size()+1;
408 OSL_ENSURE(SQL_ISRULE(pParameter,parameter),"OResultSet::AddParameter: Argument is not a Parameter");
409 OSL_ENSURE(pParameter->count() > 0,"OResultSet: error in parse tree");
410 #if OSL_DEBUG_LEVEL > 0
411 OSQLParseNode * pMark = pParameter->getChild(0);
412 OSL_UNUSED( pMark );
413 #endif
415 OUString sParameterName;
417 // set up Parameter-Column:
418 sal_Int32 eType = DataType::VARCHAR;
419 sal_uInt32 nPrecision = 255;
420 sal_Int32 nScale = 0;
421 sal_Int32 nNullable = ColumnValue::NULLABLE;
423 if (_xCol.is())
425 // Type, Precision, Scale ... utilize the selected Columns,
426 // then this Column will get the value assigned or with this
427 // Column will the value be compared.
428 eType = getINT32(_xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)));
429 nPrecision = getINT32(_xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)));
430 nScale = getINT32(_xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)));
431 nNullable = getINT32(_xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE)));
432 _xCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= sParameterName;
435 Reference<XPropertySet> xParaColumn = new connectivity::sdbcx::OColumn(sParameterName
436 ,OUString()
437 ,OUString()
438 ,OUString()
439 ,nNullable
440 ,nPrecision
441 ,nScale
442 ,eType
443 ,sal_False
444 ,sal_False
445 ,sal_False
446 ,m_pSQLIterator->isCaseSensitive()
447 ,OUString()
448 ,OUString()
449 ,OUString());
450 m_xParamColumns->get().push_back(xParaColumn);
451 return nParameter;
454 void OPreparedStatement::describeColumn(OSQLParseNode*
455 _pParameter,OSQLParseNode* _pNode,const OSQLTable& _xTable)
457 Reference<XPropertySet> xProp;
458 if(SQL_ISRULE(_pNode,column_ref))
460 OUString sColumnName,sTableRange;
461 m_pSQLIterator->getColumnRange(_pNode,sColumnName,sTableRange);
462 if(!sColumnName.isEmpty())
464 Reference<XNameAccess> xNameAccess = _xTable->getColumns();
465 if(xNameAccess->hasByName(sColumnName))
466 xNameAccess->getByName(sColumnName) >>= xProp;
467 AddParameter(_pParameter,xProp);
470 // else
471 // AddParameter(_pParameter,xProp);
474 void OPreparedStatement::describeParameter()
476 ::std::vector< OSQLParseNode*> aParseNodes;
477 scanParameter(m_pParseTree,aParseNodes);
478 if(!aParseNodes.empty())
480 m_xParamColumns = new OSQLColumns();
481 const OSQLTables& xTabs = m_pSQLIterator->getTables();
482 if(xTabs.size())
484 OSQLTable xTable = xTabs.begin()->second;
485 ::std::vector< OSQLParseNode*>::const_iterator aIter =
486 aParseNodes.begin();
487 for (;aIter != aParseNodes.end();++aIter )
489 describeColumn(*aIter,(*aIter)->getParent()->getChild(0),xTable);
496 void OPreparedStatement::scanParameter(OSQLParseNode* pParseNode,::std::vector< OSQLParseNode*>& _rParaNodes)
498 OSL_ENSURE(pParseNode != NULL,"OResultSet: internal error: invalid ParseNode");
500 // Parameter Name-Row found?
501 if (SQL_ISRULE(pParseNode,parameter))
503 OSL_ENSURE(pParseNode->count() >= 1,"OResultSet: Faulty Parse Tree");
504 OSL_ENSURE(pParseNode->getChild(0)->getNodeType() == SQL_NODE_PUNCTUATION,"OResultSet: Faulty Parse Tree");
506 _rParaNodes.push_back(pParseNode);
507 // further search isn't necessary
508 return;
511 // Search on in Parse Tree
512 for (sal_uInt32 i = 0; i < pParseNode->count(); i++)
513 scanParameter(pParseNode->getChild(i),_rParaNodes);
516 ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet > SAL_CALL OPreparedStatement::getResultSet( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
518 return NULL;
521 sal_Int32 SAL_CALL OPreparedStatement::getUpdateCount( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
523 return 0;
526 sal_Bool SAL_CALL OPreparedStatement::getMoreResults( ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
528 return sal_False;
533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */