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 .
20 #include <osl/diagnose.h>
21 #include <connectivity/sdbcx/VColumn.hxx>
22 #include "MPreparedStatement.hxx"
23 #include <com/sun/star/sdbc/DataType.hpp>
24 #include "MResultSetMetaData.hxx"
25 #include <cppuhelper/typeprovider.hxx>
26 #include <comphelper/sequence.hxx>
27 #include <com/sun/star/lang/DisposedException.hpp>
28 #include <connectivity/dbexception.hxx>
29 #include <connectivity/dbtools.hxx>
30 #include <comphelper/types.hxx>
31 #include <com/sun/star/sdbc/ColumnValue.hpp>
32 #include "diagnose_ex.h"
34 #if OSL_DEBUG_LEVEL > 0
35 # define OUtoCStr( x ) ( OUStringToOString ( (x), RTL_TEXTENCODING_ASCII_US).getStr())
36 #else /* OSL_DEBUG_LEVEL */
37 # define OUtoCStr( x ) ("dummy")
38 #endif /* OSL_DEBUG_LEVEL */
40 using namespace ::comphelper
;
41 using namespace connectivity
;
42 using namespace connectivity::mozab
;
43 using namespace com::sun::star::uno
;
44 using namespace com::sun::star::lang
;
45 using namespace com::sun::star::beans
;
46 using namespace com::sun::star::sdbc
;
47 using namespace com::sun::star::sdbcx
;
48 using namespace com::sun::star::container
;
49 using namespace com::sun::star::io
;
50 using namespace com::sun::star::util
;
52 IMPLEMENT_SERVICE_INFO(OPreparedStatement
,"com.sun.star.sdbcx.mozab.PreparedStatement","com.sun.star.sdbc.PreparedStatement");
55 OPreparedStatement::OPreparedStatement( OConnection
* _pConnection
,const OUString
& sql
)
56 :OCommonStatement(_pConnection
)
59 ,m_bPrepared(sal_False
)
64 OPreparedStatement::~OPreparedStatement()
68 void OPreparedStatement::lateInit()
70 if ( eSelect
!= parseSql( m_sSqlStatement
) )
74 void SAL_CALL
OPreparedStatement::disposing()
76 ::osl::MutexGuard
aGuard(m_aMutex
);
78 OCommonStatement::disposing();
81 if(m_aParameterRow
.is())
83 m_aParameterRow
->get().clear();
84 m_aParameterRow
= NULL
;
86 m_xParamColumns
= NULL
;
90 OCommonStatement::StatementType
OPreparedStatement::parseSql( const OUString
& sql
, sal_Bool bAdjusted
)
91 throw ( ::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
93 StatementType eStatementType
= OCommonStatement::parseSql( sql
, bAdjusted
);
94 if ( eStatementType
!= eSelect
)
95 return eStatementType
;
97 m_xParamColumns
= new OSQLColumns();
99 // describe all parameters need for the resultset
102 Reference
<XIndexAccess
> xNames(m_xColNames
,UNO_QUERY
);
103 OResultSet::setBoundedColumns( m_aRow
, m_xParamColumns
, xNames
, sal_False
, m_xDBMetaData
, m_aColMapping
);
105 return eStatementType
;
109 void OPreparedStatement::initializeResultSet( OResultSet
* _pResult
)
111 OCommonStatement::initializeResultSet( _pResult
);
112 _pResult
->setParameterColumns( m_xParamColumns
);
113 _pResult
->setParameterRow( m_aParameterRow
);
117 void OPreparedStatement::clearCachedResultSet()
119 OCommonStatement::clearCachedResultSet();
120 m_pResultSet
.clear();
124 void OPreparedStatement::cacheResultSet( const ::rtl::Reference
< OResultSet
>& _pResult
)
126 OCommonStatement::cacheResultSet( _pResult
);
127 OSL_PRECOND( m_pResultSet
== NULL
, "OPreparedStatement::parseSql: you should call clearCachedResultSet before!" );
128 m_pResultSet
= _pResult
;
132 void SAL_CALL
OPreparedStatement::acquire() throw()
134 OCommonStatement::acquire();
137 void SAL_CALL
OPreparedStatement::release() throw()
139 OCommonStatement::release();
142 Any SAL_CALL
OPreparedStatement::queryInterface( const Type
& rType
) throw(RuntimeException
)
144 Any aRet
= OCommonStatement::queryInterface(rType
);
146 aRet
= OPreparedStatement_BASE::queryInterface(rType
);
150 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> SAL_CALL
OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException
)
152 return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OCommonStatement::getTypes());
156 Reference
< XResultSetMetaData
> SAL_CALL
OPreparedStatement::getMetaData( ) throw(SQLException
, RuntimeException
)
158 ::osl::MutexGuard
aGuard( m_aMutex
);
159 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
161 sal_Bool bReadOnly
= sal_True
;
162 if ( m_pResultSet
.is() )
163 bReadOnly
= m_pResultSet
->determineReadOnly();
164 // if we do not have a result set, then we have not been executed, yet. In this case, assuming readonly=true is
167 if ( !m_xMetaData
.is() )
168 m_xMetaData
= new OResultSetMetaData( m_pSQLIterator
->getSelectColumns(), m_pSQLIterator
->getTables().begin()->first
,m_pTable
,bReadOnly
);
174 sal_Bool SAL_CALL
OPreparedStatement::execute( ) throw(SQLException
, RuntimeException
)
176 ::osl::MutexGuard
aGuard( m_aMutex
);
177 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
179 Reference
< XResultSet
> xResult
= executeQuery();
184 sal_Int32 SAL_CALL
OPreparedStatement::executeUpdate( ) throw(SQLException
, RuntimeException
)
186 ::dbtools::throwFeatureNotImplementedSQLException( "XStatement::executeUpdate", *this );
191 void SAL_CALL
OPreparedStatement::setString( sal_Int32 parameterIndex
, const OUString
& x
) throw(SQLException
, RuntimeException
)
193 ::osl::MutexGuard
aGuard( m_aMutex
);
194 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
196 OSL_TRACE("prepStmt::setString( %s )", OUtoCStr( x
) );
197 setParameter( parameterIndex
, x
);
201 Reference
< XConnection
> SAL_CALL
OPreparedStatement::getConnection( ) throw(SQLException
, RuntimeException
)
203 ::osl::MutexGuard
aGuard( m_aMutex
);
204 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
206 return (Reference
< XConnection
>)m_pConnection
;
210 Reference
< XResultSet
> SAL_CALL
OPreparedStatement::executeQuery( ) throw(SQLException
, RuntimeException
)
212 ::osl::MutexGuard
aGuard( m_aMutex
);
213 OSL_TRACE("In: OPreparedStatement::executeQuery" );
214 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
216 // our statement has already been parsed in lateInit, no need to do all this (potentially expensive)
217 // stuff again. Just execute.
218 return impl_executeCurrentQuery();
222 void SAL_CALL
OPreparedStatement::setBoolean( sal_Int32
/*parameterIndex*/, sal_Bool
/*x*/ ) throw(SQLException
, RuntimeException
)
224 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setBoolean", *this );
227 void SAL_CALL
OPreparedStatement::setByte( sal_Int32
/*parameterIndex*/, sal_Int8
/*x*/ ) throw(SQLException
, RuntimeException
)
229 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setByte", *this );
233 void SAL_CALL
OPreparedStatement::setDate( sal_Int32
/*parameterIndex*/, const Date
& /*aData*/ ) throw(SQLException
, RuntimeException
)
235 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setDate", *this );
240 void SAL_CALL
OPreparedStatement::setTime( sal_Int32
/*parameterIndex*/, const css::util::Time
& /*aVal*/ ) throw(SQLException
, RuntimeException
)
242 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setTime", *this );
246 void SAL_CALL
OPreparedStatement::setTimestamp( sal_Int32
/*parameterIndex*/, const DateTime
& /*aVal*/ ) throw(SQLException
, RuntimeException
)
248 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setTimestamp", *this );
252 void SAL_CALL
OPreparedStatement::setDouble( sal_Int32
/*parameterIndex*/, double /*x*/ ) throw(SQLException
, RuntimeException
)
254 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setDouble", *this );
259 void SAL_CALL
OPreparedStatement::setFloat( sal_Int32
/*parameterIndex*/, float /*x*/ ) throw(SQLException
, RuntimeException
)
261 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setFloat", *this );
265 void SAL_CALL
OPreparedStatement::setInt( sal_Int32
/*parameterIndex*/, sal_Int32
/*x*/ ) throw(SQLException
, RuntimeException
)
267 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setInt", *this );
271 void SAL_CALL
OPreparedStatement::setLong( sal_Int32
/*parameterIndex*/, sal_Int64
/*aVal*/ ) throw(SQLException
, RuntimeException
)
273 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setLong", *this );
277 void SAL_CALL
OPreparedStatement::setNull( sal_Int32 parameterIndex
, sal_Int32
/*sqlType*/ ) throw(SQLException
, RuntimeException
)
279 ::osl::MutexGuard
aGuard( m_aMutex
);
280 checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
282 checkAndResizeParameters(parameterIndex
);
284 (m_aParameterRow
->get())[parameterIndex
].setNull();
288 void SAL_CALL
OPreparedStatement::setClob( sal_Int32
/*parameterIndex*/, const Reference
< XClob
>& /*x*/ ) throw(SQLException
, RuntimeException
)
290 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setClob", *this );
294 void SAL_CALL
OPreparedStatement::setBlob( sal_Int32
/*parameterIndex*/, const Reference
< XBlob
>& /*x*/ ) throw(SQLException
, RuntimeException
)
296 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setBlob", *this );
300 void SAL_CALL
OPreparedStatement::setArray( sal_Int32
/*parameterIndex*/, const Reference
< XArray
>& /*x*/ ) throw(SQLException
, RuntimeException
)
302 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setArray", *this );
306 void SAL_CALL
OPreparedStatement::setRef( sal_Int32
/*parameterIndex*/, const Reference
< XRef
>& /*x*/ ) throw(SQLException
, RuntimeException
)
308 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setRef", *this );
312 void SAL_CALL
OPreparedStatement::setObjectWithInfo( sal_Int32
/*parameterIndex*/, const Any
& /*x*/, sal_Int32
/*sqlType*/, sal_Int32
/*scale*/ ) throw(SQLException
, RuntimeException
)
314 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setObjectWithInfo", *this );
318 void SAL_CALL
OPreparedStatement::setObjectNull( sal_Int32 parameterIndex
, sal_Int32 sqlType
, const OUString
& /*typeName*/ ) throw(SQLException
, RuntimeException
)
320 setNull(parameterIndex
,sqlType
);
324 void SAL_CALL
OPreparedStatement::setObject( sal_Int32 parameterIndex
, const Any
& x
) throw(SQLException
, RuntimeException
)
326 ::dbtools::implSetObject(this,parameterIndex
,x
);
330 void SAL_CALL
OPreparedStatement::setShort( sal_Int32
/*parameterIndex*/, sal_Int16
/*x*/ ) throw(SQLException
, RuntimeException
)
332 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setShort", *this );
336 void SAL_CALL
OPreparedStatement::setBytes( sal_Int32
/*parameterIndex*/, const Sequence
< sal_Int8
>& /*x*/ ) throw(SQLException
, RuntimeException
)
338 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setBytes", *this );
343 void SAL_CALL
OPreparedStatement::setCharacterStream( sal_Int32
/*parameterIndex*/, const Reference
< ::com::sun::star::io::XInputStream
>& /*x*/, sal_Int32
/*length*/ ) throw(SQLException
, RuntimeException
)
345 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setCharacterStream", *this );
349 void SAL_CALL
OPreparedStatement::setBinaryStream( sal_Int32
/*parameterIndex*/, const Reference
< ::com::sun::star::io::XInputStream
>& /*x*/, sal_Int32
/*length*/ ) throw(SQLException
, RuntimeException
)
351 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setBinaryStream", *this );
355 void SAL_CALL
OPreparedStatement::clearParameters( ) throw(SQLException
, RuntimeException
)
359 void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
,const Any
& rValue
) throw (Exception
)
363 case PROPERTY_ID_RESULTSETCONCURRENCY
:
365 case PROPERTY_ID_RESULTSETTYPE
:
367 case PROPERTY_ID_FETCHDIRECTION
:
369 case PROPERTY_ID_USEBOOKMARKS
:
372 OCommonStatement::setFastPropertyValue_NoBroadcast(nHandle
,rValue
);
377 void OPreparedStatement::checkAndResizeParameters(sal_Int32 parameterIndex
)
379 ::connectivity::checkDisposed(OCommonStatement_IBASE::rBHelper
.bDisposed
);
381 if ( !m_aParameterRow
.is() ) {
382 m_aParameterRow
= new OValueVector();
383 m_aParameterRow
->get().push_back(sal_Int32(0));
386 if ((sal_Int32
)(m_aParameterRow
->get()).size() <= parameterIndex
)
387 (m_aParameterRow
->get()).resize(parameterIndex
+1);
390 void OPreparedStatement::setParameter(sal_Int32 parameterIndex
, const
393 ::osl::MutexGuard
aGuard( m_aMutex
);
394 checkAndResizeParameters(parameterIndex
);
396 OSL_TRACE("setParameter( %d, '%s')", parameterIndex
, OUtoCStr(x
) );
397 (m_aParameterRow
->get())[parameterIndex
] = x
;
401 size_t OPreparedStatement::AddParameter(OSQLParseNode
* pParameter
, const Reference
<XPropertySet
>& _xCol
)
403 OSL_UNUSED( pParameter
);
404 // Count of the newly added Parameters
405 size_t nParameter
= m_xParamColumns
->get().size()+1;
407 OSL_ENSURE(SQL_ISRULE(pParameter
,parameter
),"OResultSet::AddParameter: Argument is not a Parameter");
408 OSL_ENSURE(pParameter
->count() > 0,"OResultSet: error in parse tree");
409 #if OSL_DEBUG_LEVEL > 0
410 OSQLParseNode
* pMark
= pParameter
->getChild(0);
414 OUString sParameterName
;
416 // set up Parameter-Column:
417 sal_Int32 eType
= DataType::VARCHAR
;
418 sal_uInt32 nPrecision
= 255;
419 sal_Int32 nScale
= 0;
420 sal_Int32 nNullable
= ColumnValue::NULLABLE
;
424 // Type, Precision, Scale ... utilize the selected Columns,
425 // then this Column will get the value assigned or with this
426 // Column will the value be compared.
427 eType
= getINT32(_xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE
)));
428 nPrecision
= getINT32(_xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION
)));
429 nScale
= getINT32(_xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE
)));
430 nNullable
= getINT32(_xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE
)));
431 _xCol
->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME
)) >>= sParameterName
;
434 Reference
<XPropertySet
> xParaColumn
= new connectivity::sdbcx::OColumn(sParameterName
445 ,m_pSQLIterator
->isCaseSensitive()
449 m_xParamColumns
->get().push_back(xParaColumn
);
453 void OPreparedStatement::describeColumn(OSQLParseNode
*
454 _pParameter
,OSQLParseNode
* _pNode
,const OSQLTable
& _xTable
)
456 Reference
<XPropertySet
> xProp
;
457 if(SQL_ISRULE(_pNode
,column_ref
))
459 OUString sColumnName
,sTableRange
;
460 m_pSQLIterator
->getColumnRange(_pNode
,sColumnName
,sTableRange
);
461 if(!sColumnName
.isEmpty())
463 Reference
<XNameAccess
> xNameAccess
= _xTable
->getColumns();
464 if(xNameAccess
->hasByName(sColumnName
))
465 xNameAccess
->getByName(sColumnName
) >>= xProp
;
466 AddParameter(_pParameter
,xProp
);
470 // AddParameter(_pParameter,xProp);
473 void OPreparedStatement::describeParameter()
475 ::std::vector
< OSQLParseNode
*> aParseNodes
;
476 scanParameter(m_pParseTree
,aParseNodes
);
477 if(!aParseNodes
.empty())
479 m_xParamColumns
= new OSQLColumns();
480 const OSQLTables
& xTabs
= m_pSQLIterator
->getTables();
483 OSQLTable xTable
= xTabs
.begin()->second
;
484 ::std::vector
< OSQLParseNode
*>::const_iterator aIter
=
486 for (;aIter
!= aParseNodes
.end();++aIter
)
488 describeColumn(*aIter
,(*aIter
)->getParent()->getChild(0),xTable
);
495 void OPreparedStatement::scanParameter(OSQLParseNode
* pParseNode
,::std::vector
< OSQLParseNode
*>& _rParaNodes
)
497 OSL_ENSURE(pParseNode
!= NULL
,"OResultSet: internal error: invalid ParseNode");
499 // Parameter Name-Row found?
500 if (SQL_ISRULE(pParseNode
,parameter
))
502 OSL_ENSURE(pParseNode
->count() >= 1,"OResultSet: Faulty Parse Tree");
503 OSL_ENSURE(pParseNode
->getChild(0)->getNodeType() == SQL_NODE_PUNCTUATION
,"OResultSet: Faulty Parse Tree");
505 _rParaNodes
.push_back(pParseNode
);
506 // further search isn't necessary
510 // Search on in Parse Tree
511 for (sal_uInt32 i
= 0; i
< pParseNode
->count(); i
++)
512 scanParameter(pParseNode
->getChild(i
),_rParaNodes
);
515 ::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
)
520 sal_Int32 SAL_CALL
OPreparedStatement::getUpdateCount( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
525 sal_Bool SAL_CALL
OPreparedStatement::getMoreResults( ) throw(::com::sun::star::sdbc::SQLException
, ::com::sun::star::uno::RuntimeException
)
532 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */