1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: MPreparedStatement.cxx,v $
10 * $Revision: 1.14.56.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
34 #include <osl/diagnose.h>
35 #include "connectivity/sdbcx/VColumn.hxx"
36 #include "MPreparedStatement.hxx"
37 #include <com/sun/star/sdbc/DataType.hpp>
38 #include "MResultSetMetaData.hxx"
39 #include <cppuhelper/typeprovider.hxx>
40 #include <comphelper/sequence.hxx>
41 #include <com/sun/star/lang/DisposedException.hpp>
42 #include "connectivity/dbexception.hxx"
43 #include "connectivity/dbtools.hxx"
44 #include <comphelper/types.hxx>
45 #include <com/sun/star/sdbc/ColumnValue.hpp>
46 #include "diagnose_ex.h"
48 #if OSL_DEBUG_LEVEL > 0
49 # define OUtoCStr( x ) ( ::rtl::OUStringToOString ( (x), RTL_TEXTENCODING_ASCII_US).getStr())
50 #else /* OSL_DEBUG_LEVEL */
51 # define OUtoCStr( x ) ("dummy")
52 #endif /* OSL_DEBUG_LEVEL */
54 using namespace ::comphelper
;
55 using namespace connectivity
;
56 using namespace connectivity::mozab
;
57 using namespace com::sun::star::uno
;
58 using namespace com::sun::star::lang
;
59 using namespace com::sun::star::beans
;
60 using namespace com::sun::star::sdbc
;
61 using namespace com::sun::star::sdbcx
;
62 using namespace com::sun::star::container
;
63 using namespace com::sun::star::io
;
64 using namespace com::sun::star::util
;
66 IMPLEMENT_SERVICE_INFO(OPreparedStatement
,"com.sun.star.sdbcx.mozab.PreparedStatement","com.sun.star.sdbc.PreparedStatement");
69 OPreparedStatement::OPreparedStatement( OConnection
* _pConnection
,const ::rtl::OUString
& sql
)
70 :OCommonStatement(_pConnection
)
73 ,m_bPrepared(sal_False
)
77 // -----------------------------------------------------------------------------
78 OPreparedStatement::~OPreparedStatement()
81 // -----------------------------------------------------------------------------
82 void OPreparedStatement::lateInit()
84 if ( eSelect
!= parseSql( m_sSqlStatement
) )
87 // -------------------------------------------------------------------------
88 void SAL_CALL
OPreparedStatement::disposing()
90 ::osl::MutexGuard
aGuard(m_aMutex
);
92 OCommonStatement::disposing();
95 if(m_aParameterRow
.isValid())
97 m_aParameterRow
->get().clear();
98 m_aParameterRow
= NULL
;
100 m_xParamColumns
= NULL
;
102 // -----------------------------------------------------------------------------
104 OCommonStatement::StatementType
OPreparedStatement::parseSql( const ::rtl::OUString
& sql
, sal_Bool bAdjusted
)
105 throw ( ::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
107 StatementType eStatementType
= OCommonStatement::parseSql( sql
, bAdjusted
);
108 if ( eStatementType
!= eSelect
)
109 return eStatementType
;
111 m_xParamColumns
= new OSQLColumns();
113 // describe all parameters need for the resultset
116 Reference
<XIndexAccess
> xNames(m_xColNames
,UNO_QUERY
);
117 OResultSet::setBoundedColumns( m_aRow
, m_xParamColumns
, xNames
, sal_False
, m_xDBMetaData
, m_aColMapping
);
119 return eStatementType
;
122 // -----------------------------------------------------------------------------
123 void OPreparedStatement::initializeResultSet( OResultSet
* _pResult
)
125 OCommonStatement::initializeResultSet( _pResult
);
126 _pResult
->setParameterColumns( m_xParamColumns
);
127 _pResult
->setParameterRow( m_aParameterRow
);
130 // -----------------------------------------------------------------------------
131 void OPreparedStatement::clearCachedResultSet()
133 OCommonStatement::clearCachedResultSet();
134 m_pResultSet
.clear();
137 // -----------------------------------------------------------------------------
138 void OPreparedStatement::cacheResultSet( const ::rtl::Reference
< OResultSet
>& _pResult
)
140 OCommonStatement::cacheResultSet( _pResult
);
141 OSL_PRECOND( m_pResultSet
== NULL
, "OPreparedStatement::parseSql: you should call clearCachedResultSet before!" );
142 m_pResultSet
= _pResult
;
145 // -----------------------------------------------------------------------------
146 void SAL_CALL
OPreparedStatement::acquire() throw()
148 OCommonStatement::acquire();
150 // -----------------------------------------------------------------------------
151 void SAL_CALL
OPreparedStatement::release() throw()
153 OCommonStatement::release();
155 // -----------------------------------------------------------------------------
156 Any SAL_CALL
OPreparedStatement::queryInterface( const Type
& rType
) throw(RuntimeException
)
158 Any aRet
= OCommonStatement::queryInterface(rType
);
160 aRet
= OPreparedStatement_BASE::queryInterface(rType
);
163 // -------------------------------------------------------------------------
164 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> SAL_CALL
OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException
)
166 return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OCommonStatement::getTypes());
168 // -------------------------------------------------------------------------
170 Reference
< XResultSetMetaData
> SAL_CALL
OPreparedStatement::getMetaData( ) throw(SQLException
, RuntimeException
)
172 ::osl::MutexGuard
aGuard( m_aMutex
);
173 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
175 sal_Bool bReadOnly
= sal_True
;
176 if ( m_pResultSet
.is() )
177 bReadOnly
= m_pResultSet
->determineReadOnly();
178 // if we do not have a result set, then we have not been executed, yet. In this case, assuming readonly=true is
181 if ( !m_xMetaData
.is() )
182 m_xMetaData
= new OResultSetMetaData( m_pSQLIterator
->getSelectColumns(), m_pSQLIterator
->getTables().begin()->first
,m_pTable
,bReadOnly
);
187 // -------------------------------------------------------------------------
188 sal_Bool SAL_CALL
OPreparedStatement::execute( ) throw(SQLException
, RuntimeException
)
190 ::osl::MutexGuard
aGuard( m_aMutex
);
191 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
193 Reference
< XResultSet
> xResult
= executeQuery();
196 // -------------------------------------------------------------------------
198 sal_Int32 SAL_CALL
OPreparedStatement::executeUpdate( ) throw(SQLException
, RuntimeException
)
200 ::dbtools::throwFeatureNotImplementedException( "XStatement::executeUpdate", *this );
203 // -------------------------------------------------------------------------
205 void SAL_CALL
OPreparedStatement::setString( sal_Int32 parameterIndex
, const ::rtl::OUString
& x
) throw(SQLException
, RuntimeException
)
207 ::osl::MutexGuard
aGuard( m_aMutex
);
208 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
210 OSL_TRACE("prepStmt::setString( %s )", OUtoCStr( x
) );
211 setParameter( parameterIndex
, x
);
213 // -------------------------------------------------------------------------
215 Reference
< XConnection
> SAL_CALL
OPreparedStatement::getConnection( ) throw(SQLException
, RuntimeException
)
217 ::osl::MutexGuard
aGuard( m_aMutex
);
218 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
220 return (Reference
< XConnection
>)m_pConnection
;
222 // -------------------------------------------------------------------------
224 Reference
< XResultSet
> SAL_CALL
OPreparedStatement::executeQuery( ) throw(SQLException
, RuntimeException
)
226 ::osl::MutexGuard
aGuard( m_aMutex
);
227 OSL_TRACE("In: OPreparedStatement::executeQuery" );
228 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
230 // our statement has already been parsed in lateInit, no need to do all this (potentially expensive)
231 // stuff again. Just execute.
232 return impl_executeCurrentQuery();
234 // -------------------------------------------------------------------------
236 void SAL_CALL
OPreparedStatement::setBoolean( sal_Int32
/*parameterIndex*/, sal_Bool
/*x*/ ) throw(SQLException
, RuntimeException
)
238 ::dbtools::throwFeatureNotImplementedException( "XParameters::setBoolean", *this );
240 // -------------------------------------------------------------------------
241 void SAL_CALL
OPreparedStatement::setByte( sal_Int32
/*parameterIndex*/, sal_Int8
/*x*/ ) throw(SQLException
, RuntimeException
)
243 ::dbtools::throwFeatureNotImplementedException( "XParameters::setByte", *this );
245 // -------------------------------------------------------------------------
247 void SAL_CALL
OPreparedStatement::setDate( sal_Int32
/*parameterIndex*/, const Date
& /*aData*/ ) throw(SQLException
, RuntimeException
)
249 ::dbtools::throwFeatureNotImplementedException( "XParameters::setDate", *this );
251 // -------------------------------------------------------------------------
254 void SAL_CALL
OPreparedStatement::setTime( sal_Int32
/*parameterIndex*/, const Time
& /*aVal*/ ) throw(SQLException
, RuntimeException
)
256 ::dbtools::throwFeatureNotImplementedException( "XParameters::setTime", *this );
258 // -------------------------------------------------------------------------
260 void SAL_CALL
OPreparedStatement::setTimestamp( sal_Int32
/*parameterIndex*/, const DateTime
& /*aVal*/ ) throw(SQLException
, RuntimeException
)
262 ::dbtools::throwFeatureNotImplementedException( "XParameters::setTimestamp", *this );
264 // -------------------------------------------------------------------------
266 void SAL_CALL
OPreparedStatement::setDouble( sal_Int32
/*parameterIndex*/, double /*x*/ ) throw(SQLException
, RuntimeException
)
268 ::dbtools::throwFeatureNotImplementedException( "XParameters::setDouble", *this );
271 // -------------------------------------------------------------------------
273 void SAL_CALL
OPreparedStatement::setFloat( sal_Int32
/*parameterIndex*/, float /*x*/ ) throw(SQLException
, RuntimeException
)
275 ::dbtools::throwFeatureNotImplementedException( "XParameters::setFloat", *this );
277 // -------------------------------------------------------------------------
279 void SAL_CALL
OPreparedStatement::setInt( sal_Int32
/*parameterIndex*/, sal_Int32
/*x*/ ) throw(SQLException
, RuntimeException
)
281 ::dbtools::throwFeatureNotImplementedException( "XParameters::setInt", *this );
283 // -------------------------------------------------------------------------
285 void SAL_CALL
OPreparedStatement::setLong( sal_Int32
/*parameterIndex*/, sal_Int64
/*aVal*/ ) throw(SQLException
, RuntimeException
)
287 ::dbtools::throwFeatureNotImplementedException( "XParameters::setLong", *this );
289 // -------------------------------------------------------------------------
291 void SAL_CALL
OPreparedStatement::setNull( sal_Int32 parameterIndex
, sal_Int32
/*sqlType*/ ) throw(SQLException
, RuntimeException
)
293 ::osl::MutexGuard
aGuard( m_aMutex
);
294 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
296 checkAndResizeParameters(parameterIndex
);
298 (m_aParameterRow
->get())[parameterIndex
].setNull();
300 // -------------------------------------------------------------------------
302 void SAL_CALL
OPreparedStatement::setClob( sal_Int32
/*parameterIndex*/, const Reference
< XClob
>& /*x*/ ) throw(SQLException
, RuntimeException
)
304 ::dbtools::throwFeatureNotImplementedException( "XParameters::setClob", *this );
306 // -------------------------------------------------------------------------
308 void SAL_CALL
OPreparedStatement::setBlob( sal_Int32
/*parameterIndex*/, const Reference
< XBlob
>& /*x*/ ) throw(SQLException
, RuntimeException
)
310 ::dbtools::throwFeatureNotImplementedException( "XParameters::setBlob", *this );
312 // -------------------------------------------------------------------------
314 void SAL_CALL
OPreparedStatement::setArray( sal_Int32
/*parameterIndex*/, const Reference
< XArray
>& /*x*/ ) throw(SQLException
, RuntimeException
)
316 ::dbtools::throwFeatureNotImplementedException( "XParameters::setArray", *this );
318 // -------------------------------------------------------------------------
320 void SAL_CALL
OPreparedStatement::setRef( sal_Int32
/*parameterIndex*/, const Reference
< XRef
>& /*x*/ ) throw(SQLException
, RuntimeException
)
322 ::dbtools::throwFeatureNotImplementedException( "XParameters::setRef", *this );
324 // -------------------------------------------------------------------------
326 void SAL_CALL
OPreparedStatement::setObjectWithInfo( sal_Int32
/*parameterIndex*/, const Any
& /*x*/, sal_Int32
/*sqlType*/, sal_Int32
/*scale*/ ) throw(SQLException
, RuntimeException
)
328 ::dbtools::throwFeatureNotImplementedException( "XParameters::setObjectWithInfo", *this );
330 // -------------------------------------------------------------------------
332 void SAL_CALL
OPreparedStatement::setObjectNull( sal_Int32 parameterIndex
, sal_Int32 sqlType
, const ::rtl::OUString
& /*typeName*/ ) throw(SQLException
, RuntimeException
)
334 setNull(parameterIndex
,sqlType
);
336 // -------------------------------------------------------------------------
338 void SAL_CALL
OPreparedStatement::setObject( sal_Int32 parameterIndex
, const Any
& x
) throw(SQLException
, RuntimeException
)
340 ::dbtools::implSetObject(this,parameterIndex
,x
);
342 // -------------------------------------------------------------------------
344 void SAL_CALL
OPreparedStatement::setShort( sal_Int32
/*parameterIndex*/, sal_Int16
/*x*/ ) throw(SQLException
, RuntimeException
)
346 ::dbtools::throwFeatureNotImplementedException( "XParameters::setShort", *this );
348 // -------------------------------------------------------------------------
350 void SAL_CALL
OPreparedStatement::setBytes( sal_Int32
/*parameterIndex*/, const Sequence
< sal_Int8
>& /*x*/ ) throw(SQLException
, RuntimeException
)
352 ::dbtools::throwFeatureNotImplementedException( "XParameters::setBytes", *this );
354 // -------------------------------------------------------------------------
357 void SAL_CALL
OPreparedStatement::setCharacterStream( sal_Int32
/*parameterIndex*/, const Reference
< ::com::sun::star::io::XInputStream
>& /*x*/, sal_Int32
/*length*/ ) throw(SQLException
, RuntimeException
)
359 ::dbtools::throwFeatureNotImplementedException( "XParameters::setCharacterStream", *this );
361 // -------------------------------------------------------------------------
363 void SAL_CALL
OPreparedStatement::setBinaryStream( sal_Int32
/*parameterIndex*/, const Reference
< ::com::sun::star::io::XInputStream
>& /*x*/, sal_Int32
/*length*/ ) throw(SQLException
, RuntimeException
)
365 ::dbtools::throwFeatureNotImplementedException( "XParameters::setBinaryStream", *this );
367 // -------------------------------------------------------------------------
369 void SAL_CALL
OPreparedStatement::clearParameters( ) throw(SQLException
, RuntimeException
)
372 // -------------------------------------------------------------------------
373 void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
,const Any
& rValue
) throw (Exception
)
377 case PROPERTY_ID_RESULTSETCONCURRENCY
:
379 case PROPERTY_ID_RESULTSETTYPE
:
381 case PROPERTY_ID_FETCHDIRECTION
:
383 case PROPERTY_ID_USEBOOKMARKS
:
386 OCommonStatement::setFastPropertyValue_NoBroadcast(nHandle
,rValue
);
389 // -----------------------------------------------------------------------------
390 void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex
)
392 if( !_parameterIndex
|| _parameterIndex
> m_nNumParams
)
393 ::dbtools::throwInvalidIndexException(*this);
395 // -----------------------------------------------------------------------------
396 void OPreparedStatement::checkAndResizeParameters(sal_Int32 parameterIndex
)
398 ::connectivity::checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
400 if ( !m_aParameterRow
.isValid() ) {
401 m_aParameterRow
= new OValueVector();
402 m_aParameterRow
->get().push_back(sal_Int32(0));
405 if ((sal_Int32
)(m_aParameterRow
->get()).size() <= parameterIndex
)
406 (m_aParameterRow
->get()).resize(parameterIndex
+1);
408 // -----------------------------------------------------------------------------
409 void OPreparedStatement::setParameter(sal_Int32 parameterIndex
, const
412 ::osl::MutexGuard
aGuard( m_aMutex
);
413 checkAndResizeParameters(parameterIndex
);
415 OSL_TRACE("setParameter( %d, '%s')", parameterIndex
, OUtoCStr(x
) );
416 (m_aParameterRow
->get())[parameterIndex
] = x
;
419 //------------------------------------------------------------------
420 sal_uInt32
OPreparedStatement::AddParameter(OSQLParseNode
* pParameter
, const Reference
<XPropertySet
>& _xCol
)
422 OSL_UNUSED( pParameter
);
423 // Nr. des neu hinzuzufuegenden Parameters:
424 sal_uInt32 nParameter
= m_xParamColumns
->get().size()+1;
426 OSL_ENSURE(SQL_ISRULE(pParameter
,parameter
),"OResultSet::AddParameter: Argument ist kein Parameter");
427 OSL_ENSURE(pParameter
->count() > 0,"OResultSet: Fehler im Parse Tree");
428 #if OSL_DEBUG_LEVEL > 0
429 OSQLParseNode
* pMark
= pParameter
->getChild(0);
433 ::rtl::OUString sParameterName
;
435 // Parameter-Column aufsetzen:
436 sal_Int32 eType
= DataType::VARCHAR
;
437 sal_uInt32 nPrecision
= 255;
438 sal_Int32 nScale
= 0;
439 sal_Int32 nNullable
= ColumnValue::NULLABLE
;
443 // Typ, Precision, Scale ... der angegebenen Column verwenden,
444 // denn dieser Column wird der Wert zugewiesen bzw. mit dieser
445 // Column wird der Wert verglichen.
446 eType
= getINT32(_xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE
)));
447 nPrecision
= getINT32(_xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION
)));
448 nScale
= getINT32(_xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE
)));
449 nNullable
= getINT32(_xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE
)));
450 _xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME
)) >>= sParameterName
;
453 Reference
<XPropertySet
> xParaColumn
= new connectivity::sdbcx::OColumn(sParameterName
463 ,m_pSQLIterator
->isCaseSensitive());
464 m_xParamColumns
->get().push_back(xParaColumn
);
467 // -----------------------------------------------------------------------------
468 void OPreparedStatement::describeColumn(OSQLParseNode
*
469 _pParameter
,OSQLParseNode
* _pNode
,const OSQLTable
& _xTable
)
471 Reference
<XPropertySet
> xProp
;
472 if(SQL_ISRULE(_pNode
,column_ref
))
474 ::rtl::OUString sColumnName
,sTableRange
;
475 m_pSQLIterator
->getColumnRange(_pNode
,sColumnName
,sTableRange
);
476 if(sColumnName
.getLength())
478 Reference
<XNameAccess
> xNameAccess
= _xTable
->getColumns();
479 if(xNameAccess
->hasByName(sColumnName
))
480 xNameAccess
->getByName(sColumnName
) >>= xProp
;
481 AddParameter(_pParameter
,xProp
);
485 // AddParameter(_pParameter,xProp);
487 // -------------------------------------------------------------------------
488 void OPreparedStatement::describeParameter()
490 ::std::vector
< OSQLParseNode
*> aParseNodes
;
491 scanParameter(m_pParseTree
,aParseNodes
);
492 if(aParseNodes
.size())
494 m_xParamColumns
= new OSQLColumns();
495 const OSQLTables
& xTabs
= m_pSQLIterator
->getTables();
498 OSQLTable xTable
= xTabs
.begin()->second
;
499 ::std::vector
< OSQLParseNode
*>::const_iterator aIter
=
501 for (;aIter
!= aParseNodes
.end();++aIter
)
503 describeColumn(*aIter
,(*aIter
)->getParent()->getChild(0),xTable
);
509 // -----------------------------------------------------------------------------
510 void OPreparedStatement::scanParameter(OSQLParseNode
* pParseNode
,::std::vector
< OSQLParseNode
*>& _rParaNodes
)
512 OSL_ENSURE(pParseNode
!= NULL
,"OResultSet: interner Fehler: ungueltiger ParseNode");
514 // Parameter Name-Regel gefunden?
515 if (SQL_ISRULE(pParseNode
,parameter
))
517 OSL_ENSURE(pParseNode
->count() >= 1,"OResultSet: Parse Tree fehlerhaft");
518 OSL_ENSURE(pParseNode
->getChild(0)->getNodeType() == SQL_NODE_PUNCTUATION
,"OResultSet: Parse Tree fehlerhaft");
520 _rParaNodes
.push_back(pParseNode
);
521 // Weiterer Abstieg nicht erforderlich
525 // Weiter absteigen im Parse Tree
526 for (sal_uInt32 i
= 0; i
< pParseNode
->count(); i
++)
527 scanParameter(pParseNode
->getChild(i
),_rParaNodes
);
529 // -----------------------------------------------------------------------------
530 ::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
)
534 // -----------------------------------------------------------------------------
535 sal_Int32 SAL_CALL
OPreparedStatement::getUpdateCount( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
539 // -----------------------------------------------------------------------------
540 sal_Bool SAL_CALL
OPreparedStatement::getMoreResults( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
544 // -----------------------------------------------------------------------------