1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <osl/diagnose.h>
31 #include "connectivity/sdbcx/VColumn.hxx"
32 #include "MPreparedStatement.hxx"
33 #include <com/sun/star/sdbc/DataType.hpp>
34 #include "MResultSetMetaData.hxx"
35 #include <cppuhelper/typeprovider.hxx>
36 #include <comphelper/sequence.hxx>
37 #include <com/sun/star/lang/DisposedException.hpp>
38 #include "connectivity/dbexception.hxx"
39 #include "connectivity/dbtools.hxx"
40 #include <comphelper/types.hxx>
41 #include <com/sun/star/sdbc/ColumnValue.hpp>
42 #include "diagnose_ex.h"
44 #if OSL_DEBUG_LEVEL > 0
45 # define OUtoCStr( x ) ( ::rtl::OUStringToOString ( (x), RTL_TEXTENCODING_ASCII_US).getStr())
46 #else /* OSL_DEBUG_LEVEL */
47 # define OUtoCStr( x ) ("dummy")
48 #endif /* OSL_DEBUG_LEVEL */
50 using namespace ::comphelper
;
51 using namespace connectivity
;
52 using namespace connectivity::mozab
;
53 using namespace com::sun::star::uno
;
54 using namespace com::sun::star::lang
;
55 using namespace com::sun::star::beans
;
56 using namespace com::sun::star::sdbc
;
57 using namespace com::sun::star::sdbcx
;
58 using namespace com::sun::star::container
;
59 using namespace com::sun::star::io
;
60 using namespace com::sun::star::util
;
62 IMPLEMENT_SERVICE_INFO(OPreparedStatement
,"com.sun.star.sdbcx.mozab.PreparedStatement","com.sun.star.sdbc.PreparedStatement");
65 OPreparedStatement::OPreparedStatement( OConnection
* _pConnection
,const ::rtl::OUString
& sql
)
66 :OCommonStatement(_pConnection
)
69 ,m_bPrepared(sal_False
)
73 // -----------------------------------------------------------------------------
74 OPreparedStatement::~OPreparedStatement()
77 // -----------------------------------------------------------------------------
78 void OPreparedStatement::lateInit()
80 if ( eSelect
!= parseSql( m_sSqlStatement
) )
83 // -------------------------------------------------------------------------
84 void SAL_CALL
OPreparedStatement::disposing()
86 ::osl::MutexGuard
aGuard(m_aMutex
);
88 OCommonStatement::disposing();
91 if(m_aParameterRow
.is())
93 m_aParameterRow
->get().clear();
94 m_aParameterRow
= NULL
;
96 m_xParamColumns
= NULL
;
98 // -----------------------------------------------------------------------------
100 OCommonStatement::StatementType
OPreparedStatement::parseSql( const ::rtl::OUString
& sql
, sal_Bool bAdjusted
)
101 throw ( ::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
103 StatementType eStatementType
= OCommonStatement::parseSql( sql
, bAdjusted
);
104 if ( eStatementType
!= eSelect
)
105 return eStatementType
;
107 m_xParamColumns
= new OSQLColumns();
109 // describe all parameters need for the resultset
112 Reference
<XIndexAccess
> xNames(m_xColNames
,UNO_QUERY
);
113 OResultSet::setBoundedColumns( m_aRow
, m_xParamColumns
, xNames
, sal_False
, m_xDBMetaData
, m_aColMapping
);
115 return eStatementType
;
118 // -----------------------------------------------------------------------------
119 void OPreparedStatement::initializeResultSet( OResultSet
* _pResult
)
121 OCommonStatement::initializeResultSet( _pResult
);
122 _pResult
->setParameterColumns( m_xParamColumns
);
123 _pResult
->setParameterRow( m_aParameterRow
);
126 // -----------------------------------------------------------------------------
127 void OPreparedStatement::clearCachedResultSet()
129 OCommonStatement::clearCachedResultSet();
130 m_pResultSet
.clear();
133 // -----------------------------------------------------------------------------
134 void OPreparedStatement::cacheResultSet( const ::rtl::Reference
< OResultSet
>& _pResult
)
136 OCommonStatement::cacheResultSet( _pResult
);
137 OSL_PRECOND( m_pResultSet
== NULL
, "OPreparedStatement::parseSql: you should call clearCachedResultSet before!" );
138 m_pResultSet
= _pResult
;
141 // -----------------------------------------------------------------------------
142 void SAL_CALL
OPreparedStatement::acquire() throw()
144 OCommonStatement::acquire();
146 // -----------------------------------------------------------------------------
147 void SAL_CALL
OPreparedStatement::release() throw()
149 OCommonStatement::release();
151 // -----------------------------------------------------------------------------
152 Any SAL_CALL
OPreparedStatement::queryInterface( const Type
& rType
) throw(RuntimeException
)
154 Any aRet
= OCommonStatement::queryInterface(rType
);
156 aRet
= OPreparedStatement_BASE::queryInterface(rType
);
159 // -------------------------------------------------------------------------
160 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> SAL_CALL
OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException
)
162 return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OCommonStatement::getTypes());
164 // -------------------------------------------------------------------------
166 Reference
< XResultSetMetaData
> SAL_CALL
OPreparedStatement::getMetaData( ) throw(SQLException
, RuntimeException
)
168 ::osl::MutexGuard
aGuard( m_aMutex
);
169 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
171 sal_Bool bReadOnly
= sal_True
;
172 if ( m_pResultSet
.is() )
173 bReadOnly
= m_pResultSet
->determineReadOnly();
174 // if we do not have a result set, then we have not been executed, yet. In this case, assuming readonly=true is
177 if ( !m_xMetaData
.is() )
178 m_xMetaData
= new OResultSetMetaData( m_pSQLIterator
->getSelectColumns(), m_pSQLIterator
->getTables().begin()->first
,m_pTable
,bReadOnly
);
183 // -------------------------------------------------------------------------
184 sal_Bool SAL_CALL
OPreparedStatement::execute( ) throw(SQLException
, RuntimeException
)
186 ::osl::MutexGuard
aGuard( m_aMutex
);
187 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
189 Reference
< XResultSet
> xResult
= executeQuery();
192 // -------------------------------------------------------------------------
194 sal_Int32 SAL_CALL
OPreparedStatement::executeUpdate( ) throw(SQLException
, RuntimeException
)
196 ::dbtools::throwFeatureNotImplementedException( "XStatement::executeUpdate", *this );
199 // -------------------------------------------------------------------------
201 void SAL_CALL
OPreparedStatement::setString( sal_Int32 parameterIndex
, const ::rtl::OUString
& x
) throw(SQLException
, RuntimeException
)
203 ::osl::MutexGuard
aGuard( m_aMutex
);
204 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
206 OSL_TRACE("prepStmt::setString( %s )", OUtoCStr( x
) );
207 setParameter( parameterIndex
, x
);
209 // -------------------------------------------------------------------------
211 Reference
< XConnection
> SAL_CALL
OPreparedStatement::getConnection( ) throw(SQLException
, RuntimeException
)
213 ::osl::MutexGuard
aGuard( m_aMutex
);
214 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
216 return (Reference
< XConnection
>)m_pConnection
;
218 // -------------------------------------------------------------------------
220 Reference
< XResultSet
> SAL_CALL
OPreparedStatement::executeQuery( ) throw(SQLException
, RuntimeException
)
222 ::osl::MutexGuard
aGuard( m_aMutex
);
223 OSL_TRACE("In: OPreparedStatement::executeQuery" );
224 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
226 // our statement has already been parsed in lateInit, no need to do all this (potentially expensive)
227 // stuff again. Just execute.
228 return impl_executeCurrentQuery();
230 // -------------------------------------------------------------------------
232 void SAL_CALL
OPreparedStatement::setBoolean( sal_Int32
/*parameterIndex*/, sal_Bool
/*x*/ ) throw(SQLException
, RuntimeException
)
234 ::dbtools::throwFeatureNotImplementedException( "XParameters::setBoolean", *this );
236 // -------------------------------------------------------------------------
237 void SAL_CALL
OPreparedStatement::setByte( sal_Int32
/*parameterIndex*/, sal_Int8
/*x*/ ) throw(SQLException
, RuntimeException
)
239 ::dbtools::throwFeatureNotImplementedException( "XParameters::setByte", *this );
241 // -------------------------------------------------------------------------
243 void SAL_CALL
OPreparedStatement::setDate( sal_Int32
/*parameterIndex*/, const Date
& /*aData*/ ) throw(SQLException
, RuntimeException
)
245 ::dbtools::throwFeatureNotImplementedException( "XParameters::setDate", *this );
247 // -------------------------------------------------------------------------
250 void SAL_CALL
OPreparedStatement::setTime( sal_Int32
/*parameterIndex*/, const Time
& /*aVal*/ ) throw(SQLException
, RuntimeException
)
252 ::dbtools::throwFeatureNotImplementedException( "XParameters::setTime", *this );
254 // -------------------------------------------------------------------------
256 void SAL_CALL
OPreparedStatement::setTimestamp( sal_Int32
/*parameterIndex*/, const DateTime
& /*aVal*/ ) throw(SQLException
, RuntimeException
)
258 ::dbtools::throwFeatureNotImplementedException( "XParameters::setTimestamp", *this );
260 // -------------------------------------------------------------------------
262 void SAL_CALL
OPreparedStatement::setDouble( sal_Int32
/*parameterIndex*/, double /*x*/ ) throw(SQLException
, RuntimeException
)
264 ::dbtools::throwFeatureNotImplementedException( "XParameters::setDouble", *this );
267 // -------------------------------------------------------------------------
269 void SAL_CALL
OPreparedStatement::setFloat( sal_Int32
/*parameterIndex*/, float /*x*/ ) throw(SQLException
, RuntimeException
)
271 ::dbtools::throwFeatureNotImplementedException( "XParameters::setFloat", *this );
273 // -------------------------------------------------------------------------
275 void SAL_CALL
OPreparedStatement::setInt( sal_Int32
/*parameterIndex*/, sal_Int32
/*x*/ ) throw(SQLException
, RuntimeException
)
277 ::dbtools::throwFeatureNotImplementedException( "XParameters::setInt", *this );
279 // -------------------------------------------------------------------------
281 void SAL_CALL
OPreparedStatement::setLong( sal_Int32
/*parameterIndex*/, sal_Int64
/*aVal*/ ) throw(SQLException
, RuntimeException
)
283 ::dbtools::throwFeatureNotImplementedException( "XParameters::setLong", *this );
285 // -------------------------------------------------------------------------
287 void SAL_CALL
OPreparedStatement::setNull( sal_Int32 parameterIndex
, sal_Int32
/*sqlType*/ ) throw(SQLException
, RuntimeException
)
289 ::osl::MutexGuard
aGuard( m_aMutex
);
290 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
292 checkAndResizeParameters(parameterIndex
);
294 (m_aParameterRow
->get())[parameterIndex
].setNull();
296 // -------------------------------------------------------------------------
298 void SAL_CALL
OPreparedStatement::setClob( sal_Int32
/*parameterIndex*/, const Reference
< XClob
>& /*x*/ ) throw(SQLException
, RuntimeException
)
300 ::dbtools::throwFeatureNotImplementedException( "XParameters::setClob", *this );
302 // -------------------------------------------------------------------------
304 void SAL_CALL
OPreparedStatement::setBlob( sal_Int32
/*parameterIndex*/, const Reference
< XBlob
>& /*x*/ ) throw(SQLException
, RuntimeException
)
306 ::dbtools::throwFeatureNotImplementedException( "XParameters::setBlob", *this );
308 // -------------------------------------------------------------------------
310 void SAL_CALL
OPreparedStatement::setArray( sal_Int32
/*parameterIndex*/, const Reference
< XArray
>& /*x*/ ) throw(SQLException
, RuntimeException
)
312 ::dbtools::throwFeatureNotImplementedException( "XParameters::setArray", *this );
314 // -------------------------------------------------------------------------
316 void SAL_CALL
OPreparedStatement::setRef( sal_Int32
/*parameterIndex*/, const Reference
< XRef
>& /*x*/ ) throw(SQLException
, RuntimeException
)
318 ::dbtools::throwFeatureNotImplementedException( "XParameters::setRef", *this );
320 // -------------------------------------------------------------------------
322 void SAL_CALL
OPreparedStatement::setObjectWithInfo( sal_Int32
/*parameterIndex*/, const Any
& /*x*/, sal_Int32
/*sqlType*/, sal_Int32
/*scale*/ ) throw(SQLException
, RuntimeException
)
324 ::dbtools::throwFeatureNotImplementedException( "XParameters::setObjectWithInfo", *this );
326 // -------------------------------------------------------------------------
328 void SAL_CALL
OPreparedStatement::setObjectNull( sal_Int32 parameterIndex
, sal_Int32 sqlType
, const ::rtl::OUString
& /*typeName*/ ) throw(SQLException
, RuntimeException
)
330 setNull(parameterIndex
,sqlType
);
332 // -------------------------------------------------------------------------
334 void SAL_CALL
OPreparedStatement::setObject( sal_Int32 parameterIndex
, const Any
& x
) throw(SQLException
, RuntimeException
)
336 ::dbtools::implSetObject(this,parameterIndex
,x
);
338 // -------------------------------------------------------------------------
340 void SAL_CALL
OPreparedStatement::setShort( sal_Int32
/*parameterIndex*/, sal_Int16
/*x*/ ) throw(SQLException
, RuntimeException
)
342 ::dbtools::throwFeatureNotImplementedException( "XParameters::setShort", *this );
344 // -------------------------------------------------------------------------
346 void SAL_CALL
OPreparedStatement::setBytes( sal_Int32
/*parameterIndex*/, const Sequence
< sal_Int8
>& /*x*/ ) throw(SQLException
, RuntimeException
)
348 ::dbtools::throwFeatureNotImplementedException( "XParameters::setBytes", *this );
350 // -------------------------------------------------------------------------
353 void SAL_CALL
OPreparedStatement::setCharacterStream( sal_Int32
/*parameterIndex*/, const Reference
< ::com::sun::star::io::XInputStream
>& /*x*/, sal_Int32
/*length*/ ) throw(SQLException
, RuntimeException
)
355 ::dbtools::throwFeatureNotImplementedException( "XParameters::setCharacterStream", *this );
357 // -------------------------------------------------------------------------
359 void SAL_CALL
OPreparedStatement::setBinaryStream( sal_Int32
/*parameterIndex*/, const Reference
< ::com::sun::star::io::XInputStream
>& /*x*/, sal_Int32
/*length*/ ) throw(SQLException
, RuntimeException
)
361 ::dbtools::throwFeatureNotImplementedException( "XParameters::setBinaryStream", *this );
363 // -------------------------------------------------------------------------
365 void SAL_CALL
OPreparedStatement::clearParameters( ) throw(SQLException
, RuntimeException
)
368 // -------------------------------------------------------------------------
369 void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
,const Any
& rValue
) throw (Exception
)
373 case PROPERTY_ID_RESULTSETCONCURRENCY
:
375 case PROPERTY_ID_RESULTSETTYPE
:
377 case PROPERTY_ID_FETCHDIRECTION
:
379 case PROPERTY_ID_USEBOOKMARKS
:
382 OCommonStatement::setFastPropertyValue_NoBroadcast(nHandle
,rValue
);
386 // -----------------------------------------------------------------------------
387 void OPreparedStatement::checkAndResizeParameters(sal_Int32 parameterIndex
)
389 ::connectivity::checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
391 if ( !m_aParameterRow
.is() ) {
392 m_aParameterRow
= new OValueVector();
393 m_aParameterRow
->get().push_back(sal_Int32(0));
396 if ((sal_Int32
)(m_aParameterRow
->get()).size() <= parameterIndex
)
397 (m_aParameterRow
->get()).resize(parameterIndex
+1);
399 // -----------------------------------------------------------------------------
400 void OPreparedStatement::setParameter(sal_Int32 parameterIndex
, const
403 ::osl::MutexGuard
aGuard( m_aMutex
);
404 checkAndResizeParameters(parameterIndex
);
406 OSL_TRACE("setParameter( %d, '%s')", parameterIndex
, OUtoCStr(x
) );
407 (m_aParameterRow
->get())[parameterIndex
] = x
;
410 //------------------------------------------------------------------
411 size_t OPreparedStatement::AddParameter(OSQLParseNode
* pParameter
, const Reference
<XPropertySet
>& _xCol
)
413 OSL_UNUSED( pParameter
);
414 // Count of the newly added Parameters
415 size_t nParameter
= m_xParamColumns
->get().size()+1;
417 OSL_ENSURE(SQL_ISRULE(pParameter
,parameter
),"OResultSet::AddParameter: Argument is not a Parameter");
418 OSL_ENSURE(pParameter
->count() > 0,"OResultSet: error in parse tree");
419 #if OSL_DEBUG_LEVEL > 0
420 OSQLParseNode
* pMark
= pParameter
->getChild(0);
424 ::rtl::OUString sParameterName
;
426 // set up Parameter-Column:
427 sal_Int32 eType
= DataType::VARCHAR
;
428 sal_uInt32 nPrecision
= 255;
429 sal_Int32 nScale
= 0;
430 sal_Int32 nNullable
= ColumnValue::NULLABLE
;
434 // Type, Precision, Scale ... utilize the selected Columns,
435 // then this Column will get the value assigned or with this
436 // Column will the value be compared.
437 eType
= getINT32(_xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE
)));
438 nPrecision
= getINT32(_xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION
)));
439 nScale
= getINT32(_xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE
)));
440 nNullable
= getINT32(_xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE
)));
441 _xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME
)) >>= sParameterName
;
444 Reference
<XPropertySet
> xParaColumn
= new connectivity::sdbcx::OColumn(sParameterName
455 ,m_pSQLIterator
->isCaseSensitive());
456 m_xParamColumns
->get().push_back(xParaColumn
);
459 // -----------------------------------------------------------------------------
460 void OPreparedStatement::describeColumn(OSQLParseNode
*
461 _pParameter
,OSQLParseNode
* _pNode
,const OSQLTable
& _xTable
)
463 Reference
<XPropertySet
> xProp
;
464 if(SQL_ISRULE(_pNode
,column_ref
))
466 ::rtl::OUString sColumnName
,sTableRange
;
467 m_pSQLIterator
->getColumnRange(_pNode
,sColumnName
,sTableRange
);
468 if(!sColumnName
.isEmpty())
470 Reference
<XNameAccess
> xNameAccess
= _xTable
->getColumns();
471 if(xNameAccess
->hasByName(sColumnName
))
472 xNameAccess
->getByName(sColumnName
) >>= xProp
;
473 AddParameter(_pParameter
,xProp
);
477 // AddParameter(_pParameter,xProp);
479 // -------------------------------------------------------------------------
480 void OPreparedStatement::describeParameter()
482 ::std::vector
< OSQLParseNode
*> aParseNodes
;
483 scanParameter(m_pParseTree
,aParseNodes
);
484 if(!aParseNodes
.empty())
486 m_xParamColumns
= new OSQLColumns();
487 const OSQLTables
& xTabs
= m_pSQLIterator
->getTables();
490 OSQLTable xTable
= xTabs
.begin()->second
;
491 ::std::vector
< OSQLParseNode
*>::const_iterator aIter
=
493 for (;aIter
!= aParseNodes
.end();++aIter
)
495 describeColumn(*aIter
,(*aIter
)->getParent()->getChild(0),xTable
);
501 // -----------------------------------------------------------------------------
502 void OPreparedStatement::scanParameter(OSQLParseNode
* pParseNode
,::std::vector
< OSQLParseNode
*>& _rParaNodes
)
504 OSL_ENSURE(pParseNode
!= NULL
,"OResultSet: internal error: invalid ParseNode");
506 // Parameter Name-Row found?
507 if (SQL_ISRULE(pParseNode
,parameter
))
509 OSL_ENSURE(pParseNode
->count() >= 1,"OResultSet: Faulty Parse Tree");
510 OSL_ENSURE(pParseNode
->getChild(0)->getNodeType() == SQL_NODE_PUNCTUATION
,"OResultSet: Faulty Parse Tree");
512 _rParaNodes
.push_back(pParseNode
);
513 // further search isn't necessary
517 // Search on in Parse Tree
518 for (sal_uInt32 i
= 0; i
< pParseNode
->count(); i
++)
519 scanParameter(pParseNode
->getChild(i
),_rParaNodes
);
521 // -----------------------------------------------------------------------------
522 ::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
)
526 // -----------------------------------------------------------------------------
527 sal_Int32 SAL_CALL
OPreparedStatement::getUpdateCount( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
531 // -----------------------------------------------------------------------------
532 sal_Bool SAL_CALL
OPreparedStatement::getMoreResults( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
536 // -----------------------------------------------------------------------------
539 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */