1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <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
)
60 ,m_bPrepared(sal_False
)
65 OPreparedStatement::~OPreparedStatement()
69 void OPreparedStatement::lateInit()
71 if ( eSelect
!= parseSql( m_sSqlStatement
) )
75 void SAL_CALL
OPreparedStatement::disposing()
77 ::osl::MutexGuard
aGuard(m_aMutex
);
79 OCommonStatement::disposing();
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
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();
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
);
147 aRet
= OPreparedStatement_BASE::queryInterface(rType
);
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
168 if ( !m_xMetaData
.is() )
169 m_xMetaData
= new OResultSetMetaData( m_pSQLIterator
->getSelectColumns(), m_pSQLIterator
->getTables().begin()->first
,m_pTable
,bReadOnly
);
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();
185 sal_Int32 SAL_CALL
OPreparedStatement::executeUpdate( ) throw(SQLException
, RuntimeException
)
187 ::dbtools::throwFeatureNotImplementedException( "XStatement::executeUpdate", *this );
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
)
364 case PROPERTY_ID_RESULTSETCONCURRENCY
:
366 case PROPERTY_ID_RESULTSETTYPE
:
368 case PROPERTY_ID_FETCHDIRECTION
:
370 case PROPERTY_ID_USEBOOKMARKS
:
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
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);
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
;
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
446 ,m_pSQLIterator
->isCaseSensitive()
450 m_xParamColumns
->get().push_back(xParaColumn
);
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
);
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();
484 OSQLTable xTable
= xTabs
.begin()->second
;
485 ::std::vector
< OSQLParseNode
*>::const_iterator aIter
=
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
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
)
521 sal_Int32 SAL_CALL
OPreparedStatement::getUpdateCount( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
526 sal_Bool SAL_CALL
OPreparedStatement::getMoreResults( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */