LibreOffice Module connectivity (master) 1
APreparedStatement.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
22#include <com/sun/star/sdbc/DataType.hpp>
24#include <ado/AResultSet.hxx>
25#include <ado/ADriver.hxx>
26#include <com/sun/star/lang/DisposedException.hpp>
31#include <comphelper/types.hxx>
34#include <rtl/ref.hxx>
35#include <strings.hrc>
36
37#include <limits>
38
39#define CHECK_RETURN(x) \
40 if(!x) \
41 ADOS::ThrowException(m_pConnection->getConnection(),*this);
42
43#ifdef max
44# undef max
45#endif
46
47using namespace connectivity::ado;
48using namespace connectivity;
49using namespace com::sun::star::uno;
50using namespace com::sun::star::lang;
51using namespace com::sun::star::beans;
52using namespace com::sun::star::sdbc;
53using namespace com::sun::star::util;
54
55IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.APreparedStatement","com.sun.star.sdbc.PreparedStatement");
56
57OPreparedStatement::OPreparedStatement( OConnection* _pConnection, const OUString& sql)
58 : OStatement_Base( _pConnection )
59{
60 osl_atomic_increment( &m_refCount );
61
62 OSQLParser aParser(_pConnection->getDriver()->getContext());
63 OUString sErrorMessage;
64 OUString sNewSql;
65 std::unique_ptr<OSQLParseNode> pNode = aParser.parseTree(sErrorMessage,sql);
66 if(pNode)
67 { // special handling for parameters
68 // we recursive replace all occurrences of ? in the statement and
69 // replace them with name like "parame" */
70 sal_Int32 nParameterCount = 0;
71 replaceParameterNodeName(pNode.get(), "parame", nParameterCount);
72 pNode->parseNodeToStr( sNewSql, _pConnection );
73 }
74 else
75 sNewSql = sql;
79 m_pParameters->AddRef();
80 m_pParameters->Refresh();
81
82 osl_atomic_decrement( &m_refCount );
83}
84
86{
87 if (m_pParameters)
88 {
89 OSL_FAIL( "OPreparedStatement::~OPreparedStatement: not disposed!" );
90 m_pParameters->Release();
91 m_pParameters = nullptr;
92 }
93}
94
95Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType )
96{
98 return aRet.hasValue() ? aRet : ::cppu::queryInterface( rType,
99 static_cast< XPreparedStatement*>(this),
100 static_cast< XParameters*>(this),
101 static_cast< XResultSetMetaDataSupplier*>(this));
102}
103
104css::uno::Sequence< css::uno::Type > SAL_CALL OPreparedStatement::getTypes( )
105{
109
110 return ::comphelper::concatSequences(aTypes.getTypes(),OStatement_Base::getTypes());
111}
112
114{
115 if(!m_xMetaData.is() && m_RecordSet.IsValid())
117 return m_xMetaData;
118}
119
121{
122 m_xMetaData.clear();
123 if (m_pParameters)
124 {
125 m_pParameters->Release();
126 m_pParameters = nullptr;
127 }
129}
130
132{
133
134 {
135 ::osl::MutexGuard aGuard( m_aMutex );
136 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
137
138 }
139 dispose();
140
141}
142
144{
145 ::osl::MutexGuard aGuard( m_aMutex );
146 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
147
148 clearWarnings ();
149
150 // Call SQLExecute
151 try {
152 ADORecordset* pSet=nullptr;
154 m_RecordSet.set(pSet);
155 }
156 catch (SQLWarning&)
157 {
158 //TODO: Save pointer to warning and save with ResultSet
159 // object once it is created.
160 }
161 return m_RecordSet.IsValid();
162}
163
165{
166 ::osl::MutexGuard aGuard( m_aMutex );
167 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
168
169
170 ADORecordset* pSet=nullptr;
173 {
175 // to be sure that we get the error really thrown
176 throw SQLException();
177 }
178 m_RecordSet.set(pSet);
180}
181
182void OPreparedStatement::setParameter(sal_Int32 parameterIndex, const DataTypeEnum& _eType,
183 sal_Int32 _nSize,const OLEVariant& Val)
184{
185 ::osl::MutexGuard aGuard( m_aMutex );
186 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
187
188
189 sal_Int32 nCount = 0;
190 m_pParameters->get_Count(&nCount);
191 if(nCount < (parameterIndex-1))
192 {
193 OUString sDefaultName = "parame" + OUString::number(parameterIndex);
194 ADOParameter* pParam = m_Command.CreateParameter(sDefaultName,_eType,adParamInput,_nSize,Val);
195 if(pParam)
196 {
197 m_pParameters->Append(pParam);
198 }
199 }
200 else
201 {
202 WpADOParameter aParam;
203 m_pParameters->get_Item(OLEVariant(sal_Int32(parameterIndex-1)),&aParam);
204 if(aParam)
205 {
206 DataTypeEnum eType = aParam.GetADOType();
207 if ( _eType != eType && _eType != adDBTimeStamp )
208 {
209 aParam.put_Type(_eType);
210 eType = _eType;
211 aParam.put_Size(_nSize);
212 }
213
214 if ( adVarBinary == eType && aParam.GetAttributes() == adParamLong )
215 {
216 aParam.AppendChunk(Val);
217 }
218 else
219 CHECK_RETURN(aParam.PutValue(Val));
220 }
221 }
223}
224
225void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const OUString& x )
226{
227 setParameter( parameterIndex, adLongVarWChar, std::numeric_limits< sal_Int32 >::max(), x );
228}
229
231{
232 ::osl::MutexGuard aGuard( m_aMutex );
233 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
234
235 return static_cast<Reference< XConnection >>(m_pConnection);
236}
237
239{
240 ::osl::MutexGuard aGuard( m_aMutex );
241 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
242
243 // first clear the old things
244 m_xMetaData.clear();
246 if(m_RecordSet.IsValid())
249
250 // then create the new ones
252 OLEVariant aCmd;
254 OLEVariant aCon;
255 aCon.setNoArg();
258 CHECK_RETURN(m_RecordSet.Open(aCmd,aCon,m_eCursorType,m_eLockType,adOpenUnspecified))
263
265 pSet->construct();
266 pSet->setMetaData(getMetaData());
268
269 return pSet;
270}
271
272void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x )
273{
274 setParameter(parameterIndex,adBoolean,sizeof(x),bool(x));
275}
276
277void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x )
278{
279 setParameter(parameterIndex,adTinyInt,sizeof(x),x);
280}
281
282void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& x )
283{
284 setParameter(parameterIndex,adDBDate,sizeof(x),x);
285}
286
287void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const css::util::Time& x )
288{
289 setParameter(parameterIndex,adDBTime,sizeof(x),x);
290}
291
292void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& x )
293{
294 setParameter(parameterIndex,adDBTimeStamp,sizeof(x),x);
295}
296
297void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x )
298{
299 setParameter(parameterIndex,adDouble,sizeof(x),x);
300}
301
302void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x )
303{
304 setParameter(parameterIndex,adSingle,sizeof(x),x);
305}
306
307void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x )
308{
309 setParameter(parameterIndex,adInteger,sizeof(x),x);
310}
311
312void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x )
313{
314 setParameter(parameterIndex,adBigInt,sizeof(x),x);
315}
316
317void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ )
318{
319 OLEVariant aVal;
320 aVal.setNull();
321 setParameter(parameterIndex,adEmpty,0,aVal);
322}
323
324void SAL_CALL OPreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ )
325{
326 ::dbtools::throwFeatureNotImplementedSQLException( "XRowUpdate::setClob", *this );
327}
328
329void SAL_CALL OPreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ )
330{
331 ::dbtools::throwFeatureNotImplementedSQLException( "XRowUpdate::setBlob", *this );
332}
333
334void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ )
335{
336 ::dbtools::throwFeatureNotImplementedSQLException( "XRowUpdate::setArray", *this );
337}
338
339void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ )
340{
341 ::dbtools::throwFeatureNotImplementedSQLException( "XRowUpdate::setRef", *this );
342}
343
344void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale )
345{
346 switch(sqlType)
347 {
348 case DataType::DECIMAL:
349 case DataType::NUMERIC:
350 setString(parameterIndex,::comphelper::getString(x));
351 break;
352 default:
353 ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
354 break;
355 }
356}
357
358void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& /*typeName*/ )
359{
360 setNull(parameterIndex,sqlType);
361}
362
363void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x )
364{
365 if(!::dbtools::implSetObject(this,parameterIndex,x))
366 {
368 STR_UNKNOWN_PARA_TYPE,
369 "$position$", OUString::number(parameterIndex)
370 ) );
372 }
373}
374
375void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x )
376{
377 setParameter(parameterIndex,adSmallInt,sizeof(x),x);
378}
379
380void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x )
381{
382 setParameter(parameterIndex,adVarBinary,sizeof(sal_Int8)*x.getLength(),x);
383}
384
385void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 /*parameterIndex*/, const Reference< css::io::XInputStream >& /*x*/, sal_Int32 /*length*/ )
386{
387 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setCharacterStream", *this );
388}
389
390void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
391{
392 if(x.is())
393 {
395 x->readBytes(aData,length);
396 setBytes(parameterIndex,aData);
397 }
398}
399
401{
402 ::osl::MutexGuard aGuard( m_aMutex );
403 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
404
405
406 if(m_pParameters)
407 {
408 sal_Int32 nCount = 0;
409 m_pParameters->get_Count(&nCount);
410 OLEVariant aVal;
411 aVal.setEmpty();
412 for(sal_Int32 i=0;i<nCount;++i)
413 {
414 WpADOParameter aParam;
415 m_pParameters->get_Item(OLEVariant(i),&aParam);
416 if(aParam)
417 {
418 CHECK_RETURN(aParam.PutValue(aVal));
419 }
420 }
421 }
422}
423
424void SAL_CALL OPreparedStatement::acquire() noexcept
425{
427}
428
429void SAL_CALL OPreparedStatement::release() noexcept
430{
432}
433
435 const OUString& _sDefaultName,
436 sal_Int32& _rParameterCount)
437{
438 sal_Int32 nCount = _pNode->count();
439 for(sal_Int32 i=0;i < nCount;++i)
440 {
441 OSQLParseNode* pChildNode = _pNode->getChild(i);
442 if(SQL_ISRULE(pChildNode,parameter) && pChildNode->count() == 1)
443 {
444 OSQLParseNode* pNewNode = new OSQLParseNode(OUString(":") ,SQLNodeType::Punctuation,0);
445 pChildNode->replaceAndDelete(pChildNode->getChild(0), pNewNode);
446 OUString sParameterName = _sDefaultName + OUString::number(++_rParameterCount);
447 pChildNode->append(new OSQLParseNode( sParameterName,SQLNodeType::Name,0));
448 }
449 else
450 replaceParameterNodeName(pChildNode,_sDefaultName,_rParameterCount);
451
452 }
453}
454
455/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define CHECK_RETURN(x)
IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.APreparedStatement","com.sun.star.sdbc.PreparedStatement")
const SharedResources & getResources() const
Definition: TConnection.hxx:65
void append(OSQLParseNode *pNewSubTree)
Definition: sqlnode.cxx:1677
void replaceAndDelete(OSQLParseNode *pOldSubTree, OSQLParseNode *pNewSubTree)
Definition: sqlnode.cxx:2377
OSQLParseNode * getChild(sal_uInt32 nPos) const
Definition: sqlnode.hxx:433
Parser for SQL92.
Definition: sqlparse.hxx:110
std::unique_ptr< OSQLParseNode > parseTree(OUString &rErrorMessage, const OUString &rStatement, bool bInternational=false)
OUString getResourceStringWithSubstitution(TranslateId pResId, const char *_pAsciiPatternToReplace, const OUString &_rStringToSubstitute) const
loads a string from the shared resource file, and replaces a given ASCII pattern with a given string
static void ThrowException(ADOConnection *_pAdoCon, const css::uno::Reference< css::uno::XInterface > &_xInterface)
Definition: ADriver.cxx:207
WpADOConnection & getConnection()
css::uno::Reference< css::uno::XComponentContext > getContext() const
Definition: ADriver.hxx:55
void setIDispatch(IDispatch *pDispInterface)
virtual void SAL_CALL release() noexcept override
virtual void SAL_CALL setBinaryStream(sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream > &x, sal_Int32 length) override
virtual void SAL_CALL setBytes(sal_Int32 parameterIndex, const css::uno::Sequence< sal_Int8 > &x) override
virtual css::uno::Reference< css::sdbc::XResultSet > SAL_CALL executeQuery() override
virtual void SAL_CALL setObject(sal_Int32 parameterIndex, const css::uno::Any &x) override
virtual void SAL_CALL setBlob(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XBlob > &x) override
virtual void SAL_CALL setNull(sal_Int32 parameterIndex, sal_Int32 sqlType) override
void setParameter(sal_Int32 parameterIndex, const DataTypeEnum &_eType, sal_Int32 _nSize, const OLEVariant &Val)
virtual void SAL_CALL setArray(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XArray > &x) override
virtual void SAL_CALL setRef(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XRef > &x) override
virtual void SAL_CALL setObjectNull(sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString &typeName) override
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
void replaceParameterNodeName(OSQLParseNode const *_pNode, const OUString &_sDefaultName, sal_Int32 &_nParameterCount)
virtual void SAL_CALL setByte(sal_Int32 parameterIndex, sal_Int8 x) override
virtual void SAL_CALL setTime(sal_Int32 parameterIndex, const css::util::Time &x) override
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
virtual void SAL_CALL setTimestamp(sal_Int32 parameterIndex, const css::util::DateTime &x) override
virtual void SAL_CALL setClob(sal_Int32 parameterIndex, const css::uno::Reference< css::sdbc::XClob > &x) override
virtual void SAL_CALL setBoolean(sal_Int32 parameterIndex, sal_Bool x) override
virtual void SAL_CALL setDate(sal_Int32 parameterIndex, const css::util::Date &x) override
virtual void SAL_CALL setDouble(sal_Int32 parameterIndex, double x) override
virtual void SAL_CALL setShort(sal_Int32 parameterIndex, sal_Int16 x) override
virtual void SAL_CALL setString(sal_Int32 parameterIndex, const OUString &x) override
virtual void SAL_CALL setInt(sal_Int32 parameterIndex, sal_Int32 x) override
virtual sal_Int32 SAL_CALL executeUpdate() override
virtual css::uno::Reference< css::sdbc::XConnection > SAL_CALL getConnection() override
virtual void SAL_CALL setCharacterStream(sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream > &x, sal_Int32 length) override
virtual void SAL_CALL setObjectWithInfo(sal_Int32 parameterIndex, const css::uno::Any &x, sal_Int32 targetSqlType, sal_Int32 scale) override
virtual css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL getMetaData() override
virtual sal_Bool SAL_CALL execute() override
virtual void SAL_CALL clearParameters() override
css::uno::Reference< css::sdbc::XResultSetMetaData > m_xMetaData
virtual void SAL_CALL disposing() override
virtual void SAL_CALL close() override
virtual void SAL_CALL setFloat(sal_Int32 parameterIndex, float x) override
virtual void SAL_CALL setLong(sal_Int32 parameterIndex, sal_Int64 x) override
virtual void SAL_CALL acquire() noexcept override
virtual void SAL_CALL acquire() noexcept override
Definition: AStatement.cxx:847
css::uno::WeakReference< css::sdbc::XResultSet > m_xResultSet
Definition: AStatement.hxx:62
virtual void SAL_CALL clearWarnings() override
Definition: AStatement.cxx:476
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
Definition: AStatement.cxx:121
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
virtual void SAL_CALL disposing() override
Definition: AStatement.cxx:89
virtual void SAL_CALL release() noexcept override
Definition: AStatement.cxx:110
ADOParameters * get_Parameters() const
Definition: Awrapado.cxx:345
bool put_Prepared(VARIANT_BOOL bPrepared) const
Definition: Awrapado.cxx:323
ADOParameter * CreateParameter(std::u16string_view _bstr, DataTypeEnum Type, ParameterDirectionEnum Direction, long nSize, const OLEVariant &Value)
Definition: Awrapado.cxx:335
bool Execute(OLEVariant &RecordsAffected, OLEVariant &Parameters, long Options, ADORecordset **ppiRset)
Definition: Awrapado.cxx:329
bool put_CommandText(std::u16string_view aCon)
Definition: Awrapado.cxx:292
bool PutValue(const OLEVariant &aVariant)
Definition: Awrapado.cxx:962
sal_Int32 GetAttributes() const
Definition: Awrapado.cxx:916
DataTypeEnum GetADOType() const
Definition: Awrapado.cxx:902
bool put_Size(sal_Int32 _nSize)
Definition: Awrapado.cxx:972
void put_Type(const DataTypeEnum &_eType)
Definition: Awrapado.cxx:910
bool AppendChunk(const OLEVariant &aVariant)
Definition: Awrapado.cxx:967
bool get_CacheSize(sal_Int32 &_nRet) const
Definition: Awrapado.cxx:876
bool put_MaxRecords(ADO_LONGPTR _nRet)
Definition: Awrapado.cxx:846
bool put_CacheSize(sal_Int32 _nRet)
Definition: Awrapado.cxx:882
bool Open(VARIANT Source, VARIANT ActiveConnection, CursorTypeEnum CursorType, LockTypeEnum LockType, sal_Int32 Options)
Definition: Awrapado.cxx:668
bool get_CursorType(CursorTypeEnum &_nRet) const
Definition: Awrapado.cxx:852
bool get_LockType(LockTypeEnum &_nRet) const
Definition: Awrapado.cxx:864
bool get_MaxRecords(ADO_LONGPTR &_nRet) const
Definition: Awrapado.cxx:840
mutable::osl::Mutex m_aMutex
int nCount
ULONG m_refCount
float x
DocumentType eType
constexpr OUStringLiteral aData
Type
void checkDisposed(bool _bThrow)
Definition: dbtools.cxx:1951
bool implSetObject(const Reference< XParameters > &_rxParameters, const sal_Int32 _nColumnIndex, const Any &_rValue)
Definition: dbtools.cxx:1516
void throwFeatureNotImplementedSQLException(const OUString &_rFeatureName, const Reference< XInterface > &_rxContext, const Any &_rNextException)
void setObjectWithInfo(const Reference< XParameters > &_xParams, sal_Int32 parameterIndex, const Any &x, sal_Int32 sqlType, sal_Int32 scale)
Definition: dbtools.cxx:1765
void throwGenericSQLException(const OUString &_rMsg, const css::uno::Reference< css::uno::XInterface > &_rxSource)
throw a generic SQLException, i.e.
int i
void dispose()
sal_Int32 scale
Definition: pq_statics.cxx:62
#define VT_ERROR
#define SQL_ISRULE(pParseNode, eRule)
Definition: sqlnode.hxx:439
unsigned char sal_Bool
signed char sal_Int8
const SvXMLTokenMapEntry aTypes[]