Branch data Line data Source code
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 : :
20 : :
21 : : #include <stdio.h>
22 : : #include <string.h>
23 : : #include <osl/diagnose.h>
24 : : #include "diagnose_ex.h"
25 : : #include "odbc/OPreparedStatement.hxx"
26 : : #include "odbc/OBoundParam.hxx"
27 : : #include <com/sun/star/sdbc/DataType.hpp>
28 : : #include "odbc/OTools.hxx"
29 : : #include "odbc/ODriver.hxx"
30 : : #include "odbc/OResultSet.hxx"
31 : : #include "odbc/OResultSetMetaData.hxx"
32 : : #include <cppuhelper/typeprovider.hxx>
33 : : #include <comphelper/sequence.hxx>
34 : : #include <com/sun/star/lang/DisposedException.hpp>
35 : : #include "connectivity/dbtools.hxx"
36 : : #include <comphelper/types.hxx>
37 : : #include "connectivity/FValue.hxx"
38 : : #include "resource/common_res.hrc"
39 : : #include "connectivity/sqlparse.hxx"
40 : :
41 : : using namespace ::comphelper;
42 : : using namespace connectivity;
43 : : using namespace connectivity::odbc;
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;
52 : :
53 : 0 : IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement");
54 : :
55 : :
56 : 0 : OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const ::rtl::OUString& sql)
57 : : :OStatement_BASE2(_pConnection)
58 : : ,numParams(0)
59 : : ,boundParams(NULL)
60 : 0 : ,m_bPrepared(sal_False)
61 : : {
62 : 0 : m_sSqlStatement = sql;
63 : : try
64 : : {
65 : 0 : if(_pConnection->isParameterSubstitutionEnabled())
66 : : {
67 : 0 : OSQLParser aParser(_pConnection->getDriver()->getORB());
68 : 0 : ::rtl::OUString sErrorMessage;
69 : 0 : ::rtl::OUString sNewSql;
70 : 0 : ::std::auto_ptr<OSQLParseNode> pNode( aParser.parseTree(sErrorMessage,sql) );
71 : 0 : if ( pNode.get() )
72 : : { // special handling for parameters
73 : 0 : OSQLParseNode::substituteParameterNames(pNode.get());
74 : 0 : pNode->parseNodeToStr( sNewSql, _pConnection );
75 : 0 : m_sSqlStatement = sNewSql;
76 : 0 : }
77 : : }
78 : : }
79 : 0 : catch(Exception&)
80 : : {
81 : : }
82 : 0 : }
83 : : // -----------------------------------------------------------------------------
84 : 0 : void SAL_CALL OPreparedStatement::acquire() throw()
85 : : {
86 : 0 : OStatement_BASE2::acquire();
87 : 0 : }
88 : : // -----------------------------------------------------------------------------
89 : 0 : void SAL_CALL OPreparedStatement::release() throw()
90 : : {
91 : 0 : OStatement_BASE2::release();
92 : 0 : }
93 : : // -----------------------------------------------------------------------------
94 : 0 : Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException)
95 : : {
96 : 0 : Any aRet = OStatement_BASE2::queryInterface(rType);
97 : 0 : return aRet.hasValue() ? aRet : OPreparedStatement_BASE::queryInterface(rType);
98 : : }
99 : : // -------------------------------------------------------------------------
100 : 0 : ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException)
101 : : {
102 : 0 : return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OStatement_BASE2::getTypes());
103 : : }
104 : : // -------------------------------------------------------------------------
105 : :
106 : 0 : Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( ) throw(SQLException, RuntimeException)
107 : : {
108 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
109 : 0 : checkDisposed(OStatement_BASE::rBHelper.bDisposed);
110 : :
111 : :
112 : 0 : prepareStatement();
113 : : OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
114 : 0 : if(!m_xMetaData.is())
115 : 0 : m_xMetaData = new OResultSetMetaData(getOwnConnection(),m_aStatementHandle);
116 : 0 : return m_xMetaData;
117 : : }
118 : : // -------------------------------------------------------------------------
119 : :
120 : 0 : void SAL_CALL OPreparedStatement::close( ) throw(SQLException, RuntimeException)
121 : : {
122 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
123 : 0 : checkDisposed(OStatement_BASE::rBHelper.bDisposed);
124 : :
125 : :
126 : : // Close/clear our result set
127 : 0 : clearMyResultSet ();
128 : :
129 : : // Reset last warning message
130 : :
131 : : try {
132 : 0 : clearWarnings ();
133 : 0 : OStatement_BASE2::close();
134 : 0 : FreeParams();
135 : : }
136 : 0 : catch (SQLException &) {
137 : : // If we get an error, ignore
138 : 0 : }
139 : :
140 : : // Remove this Statement object from the Connection object's
141 : : // list
142 : 0 : }
143 : : // -------------------------------------------------------------------------
144 : :
145 : 0 : sal_Bool SAL_CALL OPreparedStatement::execute( ) throw(SQLException, RuntimeException)
146 : : {
147 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
148 : 0 : checkDisposed(OStatement_BASE::rBHelper.bDisposed);
149 : :
150 : :
151 : 0 : sal_Bool needData = sal_False;
152 : :
153 : : // Reset warnings
154 : :
155 : 0 : clearWarnings ();
156 : :
157 : : // Reset the statement handle, warning and saved Resultset
158 : :
159 : 0 : reset();
160 : :
161 : : // Call SQLExecute
162 : 0 : prepareStatement();
163 : :
164 : : OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
165 : : try
166 : : {
167 : 0 : SQLRETURN nReturn = N3SQLExecute(m_aStatementHandle);
168 : :
169 : 0 : OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
170 : 0 : needData = nReturn == SQL_NEED_DATA;
171 : :
172 : : // Now loop while more data is needed (i.e. a data-at-
173 : : // execution parameter was given). For each parameter
174 : : // that needs data, put the data from the input stream.
175 : :
176 : 0 : while (needData) {
177 : :
178 : : // Get the parameter number that requires data
179 : :
180 : 0 : sal_Int32* paramIndex = 0;
181 : 0 : nReturn = N3SQLParamData(m_aStatementHandle,(SQLPOINTER*)¶mIndex);
182 : :
183 : : // If the parameter index is -1, there is no
184 : : // more data required
185 : :
186 : 0 : if ( !paramIndex || ( *paramIndex == -1 ) )
187 : 0 : needData = sal_False;
188 : : else
189 : : {
190 : : // Now we have the proper parameter
191 : : // index, get the data from the input
192 : : // stream and do a SQLPutData
193 : 0 : putParamData (*paramIndex);
194 : : }
195 : : }
196 : :
197 : : }
198 : 0 : catch (const SQLWarning&)
199 : : {
200 : : }
201 : :
202 : : // Now loop while more data is needed (i.e. a data-at-
203 : : // execution parameter was given). For each parameter
204 : : // that needs data, put the data from the input stream.
205 : :
206 : 0 : while (needData) {
207 : :
208 : : // Get the parameter number that requires data
209 : :
210 : 0 : sal_Int32* paramIndex = 0;
211 : 0 : N3SQLParamData (m_aStatementHandle,(SQLPOINTER*)¶mIndex);
212 : :
213 : : // If the parameter index is -1, there is no more
214 : : // data required
215 : :
216 : 0 : if (*paramIndex == -1) {
217 : 0 : needData = sal_False;
218 : : }
219 : : else {
220 : : // Now we have the proper parameter index,
221 : : // get the data from the input stream
222 : : // and do a SQLPutData
223 : 0 : putParamData(*paramIndex);
224 : : }
225 : : }
226 : :
227 : : // Now determine if there is a result set associated with
228 : : // the SQL statement that was executed. Get the column
229 : : // count, and if it is not zero, there is a result set.
230 : :
231 : :
232 : 0 : return getColumnCount() > 0;
233 : : }
234 : : // -------------------------------------------------------------------------
235 : :
236 : 0 : sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( ) throw(SQLException, RuntimeException)
237 : : {
238 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
239 : 0 : checkDisposed(OStatement_BASE::rBHelper.bDisposed);
240 : :
241 : 0 : sal_Int32 numRows = -1;
242 : :
243 : 0 : prepareStatement();
244 : : // Execute the statement. If execute returns sal_False, a
245 : : // row count exists.
246 : :
247 : 0 : if (!execute())
248 : 0 : numRows = getUpdateCount ();
249 : : else
250 : : {
251 : : // No update count was produced (a ResultSet was). Raise
252 : : // an exception
253 : 0 : m_pConnection->throwGenericSQLException(STR_NO_ROWCOUNT,*this);
254 : : }
255 : 0 : return numRows;
256 : : }
257 : : // -------------------------------------------------------------------------
258 : :
259 : 0 : void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException)
260 : : {
261 : 0 : ::rtl::OString aString(::rtl::OUStringToOString(x,getOwnConnection()->getTextEncoding()));
262 : 0 : setParameter(parameterIndex,DataType::CHAR,aString.getLength(),(void*)&x);
263 : 0 : }
264 : : // -------------------------------------------------------------------------
265 : :
266 : 0 : Reference< XConnection > SAL_CALL OPreparedStatement::getConnection( ) throw(SQLException, RuntimeException)
267 : : {
268 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
269 : 0 : checkDisposed(OStatement_BASE::rBHelper.bDisposed);
270 : :
271 : 0 : return (Reference< XConnection >)m_pConnection;
272 : : }
273 : : // -------------------------------------------------------------------------
274 : :
275 : 0 : Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( ) throw(SQLException, RuntimeException)
276 : : {
277 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
278 : 0 : checkDisposed(OStatement_BASE::rBHelper.bDisposed);
279 : :
280 : 0 : Reference< XResultSet > rs = NULL;
281 : :
282 : 0 : prepareStatement();
283 : :
284 : 0 : if (execute())
285 : 0 : rs = getResultSet(sal_False);
286 : : else
287 : : {
288 : : // No ResultSet was produced. Raise an exception
289 : 0 : m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this);
290 : : }
291 : 0 : return rs;
292 : : }
293 : : // -------------------------------------------------------------------------
294 : :
295 : 0 : void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException)
296 : : {
297 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
298 : 0 : checkDisposed(OStatement_BASE::rBHelper.bDisposed);
299 : :
300 : :
301 : 0 : sal_Int32 value = 0;
302 : :
303 : : // If the parameter is sal_True, set the value to 1
304 : 0 : if (x) {
305 : 0 : value = 1;
306 : : }
307 : :
308 : : // Set the parameter as if it were an integer
309 : 0 : setInt (parameterIndex, value);
310 : 0 : }
311 : : // -------------------------------------------------------------------------
312 : 0 : void OPreparedStatement::setParameter(sal_Int32 parameterIndex,sal_Int32 _nType,sal_Int32 _nSize,void* _pData)
313 : : {
314 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
315 : 0 : checkDisposed(OStatement_BASE::rBHelper.bDisposed);
316 : :
317 : 0 : prepareStatement();
318 : : // Allocate a buffer to be used in binding. This will be
319 : : // a 'permanent' buffer that the bridge will fill in with
320 : : // the bound data in native format.
321 : :
322 : :
323 : 0 : checkParameterIndex(parameterIndex);
324 : 0 : sal_Int32 nRealSize = _nSize;
325 : 0 : SQLSMALLINT fSqlType = static_cast<SQLSMALLINT>(OTools::jdbcTypeToOdbc(_nType));
326 : 0 : switch(fSqlType)
327 : : {
328 : : case SQL_CHAR:
329 : : case SQL_VARCHAR:
330 : : case SQL_DECIMAL:
331 : : case SQL_NUMERIC:
332 : 0 : ++nRealSize;
333 : 0 : break;
334 : : case SQL_BINARY:
335 : : case SQL_VARBINARY:
336 : 0 : nRealSize=1; //dummy buffer, binary data isn't copied
337 : 0 : break;
338 : : default:
339 : 0 : break;
340 : : }
341 : :
342 : 0 : sal_Int8* bindBuf = allocBindBuf(parameterIndex, nRealSize);
343 : :
344 : : OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
345 : : OTools::bindParameter( m_pConnection,
346 : : m_aStatementHandle,
347 : : parameterIndex,
348 : : bindBuf,
349 : : getLengthBuf(parameterIndex),
350 : : fSqlType,
351 : : sal_False,
352 : 0 : m_pConnection->useOldDateFormat(),
353 : : _pData,
354 : : (Reference <XInterface>)*this,
355 : 0 : getOwnConnection()->getTextEncoding());
356 : 0 : }
357 : : // -----------------------------------------------------------------------------
358 : 0 : void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException)
359 : : {
360 : 0 : setParameter(parameterIndex,DataType::TINYINT,sizeof(sal_Int8),&x);
361 : 0 : }
362 : : // -------------------------------------------------------------------------
363 : :
364 : 0 : void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& aData ) throw(SQLException, RuntimeException)
365 : : {
366 : 0 : DATE_STRUCT x = OTools::DateToOdbcDate(aData);
367 : 0 : setParameter(parameterIndex,DataType::DATE,sizeof(DATE_STRUCT),&x);
368 : 0 : }
369 : : // -------------------------------------------------------------------------
370 : :
371 : :
372 : 0 : void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& aVal ) throw(SQLException, RuntimeException)
373 : : {
374 : 0 : TIME_STRUCT x = OTools::TimeToOdbcTime(aVal);
375 : 0 : setParameter(parameterIndex,DataType::TIME,sizeof(TIME_STRUCT),&x);
376 : 0 : }
377 : : // -------------------------------------------------------------------------
378 : :
379 : 0 : void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& aVal ) throw(SQLException, RuntimeException)
380 : : {
381 : 0 : TIMESTAMP_STRUCT x = OTools::DateTimeToTimestamp(aVal);
382 : 0 : setParameter(parameterIndex,DataType::TIMESTAMP,sizeof(TIMESTAMP_STRUCT),&x);
383 : 0 : }
384 : : // -------------------------------------------------------------------------
385 : :
386 : 0 : void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException)
387 : : {
388 : 0 : setParameter(parameterIndex,DataType::DOUBLE,sizeof(double),&x);
389 : 0 : }
390 : :
391 : : // -------------------------------------------------------------------------
392 : :
393 : 0 : void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException)
394 : : {
395 : 0 : setParameter(parameterIndex,DataType::FLOAT,sizeof(float),&x);
396 : 0 : }
397 : : // -------------------------------------------------------------------------
398 : :
399 : 0 : void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException)
400 : : {
401 : 0 : setParameter(parameterIndex,DataType::INTEGER,sizeof(sal_Int32),&x);
402 : 0 : }
403 : : // -------------------------------------------------------------------------
404 : :
405 : 0 : void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException)
406 : : {
407 : : try
408 : : {
409 : 0 : setParameter(parameterIndex,DataType::BIGINT,sizeof(sal_Int64),&x);
410 : : }
411 : 0 : catch(SQLException&)
412 : : {
413 : 0 : setString(parameterIndex,ORowSetValue(x));
414 : : }
415 : 0 : }
416 : : // -------------------------------------------------------------------------
417 : :
418 : 0 : void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(SQLException, RuntimeException)
419 : : {
420 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
421 : 0 : checkDisposed(OStatement_BASE::rBHelper.bDisposed);
422 : :
423 : :
424 : 0 : prepareStatement();
425 : : // Get the buffer needed for the length
426 : 0 : checkParameterIndex(parameterIndex);
427 : :
428 : 0 : sal_Int8* lenBuf = getLengthBuf (parameterIndex);
429 : 0 : *(SQLLEN*)lenBuf = SQL_NULL_DATA;
430 : :
431 : :
432 : 0 : SQLLEN prec = 0;
433 : 0 : SQLULEN nColumnSize = 0;
434 : 0 : if (sqlType == SQL_CHAR || sqlType == SQL_VARCHAR || sqlType == SQL_LONGVARCHAR)
435 : : {
436 : 0 : prec = 1;
437 : 0 : nColumnSize = 1;
438 : : }
439 : :
440 : 0 : SQLSMALLINT fCType = 0;
441 : 0 : SQLSMALLINT fSqlType = 0;
442 : :
443 : 0 : SQLSMALLINT nDecimalDigits = 0;
444 : : OTools::getBindTypes( sal_False,
445 : 0 : m_pConnection->useOldDateFormat(),
446 : : (SQLSMALLINT)sqlType,
447 : : fCType,
448 : 0 : fSqlType);
449 : :
450 : 0 : SQLRETURN nReturn = N3SQLBindParameter( m_aStatementHandle,
451 : : (SQLUSMALLINT)parameterIndex,
452 : : (SQLSMALLINT)SQL_PARAM_INPUT,
453 : : fCType,
454 : : fSqlType,
455 : : nColumnSize,
456 : : nDecimalDigits,
457 : : NULL,
458 : : prec,
459 : : (SQLLEN*)lenBuf
460 : : );
461 : 0 : OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
462 : 0 : }
463 : : // -------------------------------------------------------------------------
464 : :
465 : 0 : void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x ) throw(SQLException, RuntimeException)
466 : : {
467 : 0 : if ( x.is() )
468 : 0 : setStream(parameterIndex, x->getCharacterStream(), (SQLLEN)x->length(), DataType::LONGVARCHAR);
469 : 0 : }
470 : : // -------------------------------------------------------------------------
471 : :
472 : 0 : void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x ) throw(SQLException, RuntimeException)
473 : : {
474 : 0 : if ( x.is() )
475 : 0 : setStream(parameterIndex, x->getBinaryStream(), (SQLLEN)x->length(), DataType::LONGVARCHAR);
476 : 0 : }
477 : : // -------------------------------------------------------------------------
478 : :
479 : 0 : void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException)
480 : : {
481 : 0 : ::dbtools::throwFunctionNotSupportedException( "XParameters::setArray", *this );
482 : 0 : }
483 : : // -------------------------------------------------------------------------
484 : :
485 : 0 : void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException)
486 : : {
487 : 0 : ::dbtools::throwFunctionNotSupportedException( "XParameters::setRef", *this );
488 : 0 : }
489 : : // -------------------------------------------------------------------------
490 : 0 : void OPreparedStatement::setDecimal( sal_Int32 parameterIndex, const ::rtl::OUString& x )
491 : : {
492 : 0 : ::rtl::OString aString(::rtl::OUStringToOString(x,getOwnConnection()->getTextEncoding()));
493 : 0 : setParameter(parameterIndex,DataType::DECIMAL,aString.getLength(),(void*)&x);
494 : 0 : }
495 : : // -------------------------------------------------------------------------
496 : 0 : void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException)
497 : : {
498 : 0 : checkDisposed(OStatement_BASE::rBHelper.bDisposed);
499 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
500 : :
501 : 0 : prepareStatement();
502 : : // For each known SQL Type, call the appropriate
503 : : // set routine
504 : :
505 : 0 : switch (sqlType)
506 : : {
507 : : case DataType::VARCHAR:
508 : : case DataType::LONGVARCHAR:
509 : 0 : if(x.hasValue())
510 : : {
511 : 0 : ::rtl::OUString sStr;
512 : 0 : x >>= sStr;
513 : 0 : ::rtl::OString aString(::rtl::OUStringToOString(sStr,getOwnConnection()->getTextEncoding()));
514 : 0 : setParameter(parameterIndex,sqlType,aString.getLength(),&aString);
515 : : }
516 : : else
517 : 0 : setNull(parameterIndex,sqlType);
518 : 0 : break;
519 : : case DataType::DECIMAL:
520 : : {
521 : 0 : ORowSetValue aValue;
522 : 0 : aValue.fill(x);
523 : 0 : setDecimal(parameterIndex,aValue);
524 : : }
525 : 0 : break;
526 : : case DataType::NUMERIC:
527 : : {
528 : 0 : ORowSetValue aValue;
529 : 0 : aValue.fill(x);
530 : 0 : setString(parameterIndex,aValue);
531 : : }
532 : 0 : break;
533 : : default:
534 : 0 : ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
535 : 0 : }
536 : 0 : }
537 : : // -------------------------------------------------------------------------
538 : :
539 : 0 : void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ ) throw(SQLException, RuntimeException)
540 : : {
541 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
542 : 0 : checkDisposed(OStatement_BASE::rBHelper.bDisposed);
543 : :
544 : 0 : setNull(parameterIndex,sqlType);
545 : 0 : }
546 : : // -------------------------------------------------------------------------
547 : :
548 : 0 : void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException)
549 : : {
550 : 0 : if (!::dbtools::implSetObject(this, parameterIndex, x))
551 : : { // there is no other setXXX call which can handle the value in x
552 : 0 : throw SQLException();
553 : : }
554 : 0 : }
555 : : // -------------------------------------------------------------------------
556 : :
557 : 0 : void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException)
558 : : {
559 : 0 : setParameter(parameterIndex,DataType::SMALLINT,sizeof(sal_Int16),&x);
560 : 0 : }
561 : : // -------------------------------------------------------------------------
562 : :
563 : 0 : void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException)
564 : : {
565 : 0 : setParameter(parameterIndex,DataType::BINARY,x.getLength(),(void*)&x);
566 : 0 : boundParams[parameterIndex-1].setSequence(x); // this assures that the sequence stays alive
567 : 0 : }
568 : : // -------------------------------------------------------------------------
569 : :
570 : :
571 : 0 : void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
572 : : {
573 : 0 : setStream(parameterIndex, x, length, DataType::LONGVARCHAR);
574 : 0 : }
575 : : // -------------------------------------------------------------------------
576 : :
577 : 0 : void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
578 : : {
579 : 0 : setStream(parameterIndex, x, length, DataType::LONGVARBINARY);
580 : 0 : }
581 : : // -------------------------------------------------------------------------
582 : :
583 : 0 : void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException)
584 : : {
585 : 0 : prepareStatement();
586 : : OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
587 : 0 : SQLRETURN nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_RESET_PARAMS);
588 : 0 : nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_UNBIND);
589 : : OSL_UNUSED(nRet);
590 : 0 : }
591 : : // -------------------------------------------------------------------------
592 : 0 : void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeException)
593 : : {
594 : : // clearParameters( );
595 : : // m_aBatchList.erase();
596 : 0 : }
597 : : // -------------------------------------------------------------------------
598 : :
599 : 0 : void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException)
600 : : {
601 : 0 : }
602 : : // -------------------------------------------------------------------------
603 : :
604 : 0 : Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch( ) throw(SQLException, RuntimeException)
605 : : {
606 : 0 : return Sequence< sal_Int32 > ();
607 : : }
608 : : // -------------------------------------------------------------------------
609 : :
610 : : //====================================================================
611 : : // methods
612 : : //====================================================================
613 : :
614 : : //--------------------------------------------------------------------
615 : : // initBoundParam
616 : : // Initialize the bound parameter objects
617 : : //--------------------------------------------------------------------
618 : :
619 : 0 : void OPreparedStatement::initBoundParam () throw(SQLException)
620 : : {
621 : : OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
622 : : // Get the number of parameters
623 : 0 : numParams = 0;
624 : 0 : N3SQLNumParams (m_aStatementHandle,&numParams);
625 : :
626 : : // There are parameter markers, allocate the bound
627 : : // parameter objects
628 : :
629 : 0 : if (numParams > 0)
630 : : {
631 : : // Allocate an array of bound parameter objects
632 : :
633 : 0 : boundParams = new OBoundParam[numParams];
634 : :
635 : : // initialize each bound parameter
636 : :
637 : 0 : for (sal_Int32 i = 0; i < numParams; i++)
638 : : {
639 : 0 : boundParams[i].initialize ();
640 : : }
641 : : }
642 : 0 : }
643 : : // -------------------------------------------------------------------------
644 : :
645 : : //--------------------------------------------------------------------
646 : : // allocBindBuf
647 : : // Allocate storage for the permanent data buffer for the bound
648 : : // parameter.
649 : : //--------------------------------------------------------------------
650 : :
651 : 0 : sal_Int8* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen)
652 : : {
653 : 0 : sal_Int8* b = NULL;
654 : :
655 : : // Sanity check the parameter number
656 : :
657 : 0 : if ((index >= 1) &&
658 : : (index <= numParams) && bufLen > 0 )
659 : : {
660 : 0 : b = boundParams[index - 1].allocBindDataBuffer(bufLen);
661 : : }
662 : :
663 : 0 : return b;
664 : : }
665 : : // -------------------------------------------------------------------------
666 : :
667 : : //--------------------------------------------------------------------
668 : : // getLengthBuf
669 : : // Gets the length buffer for the given parameter index
670 : : //--------------------------------------------------------------------
671 : :
672 : 0 : sal_Int8* OPreparedStatement::getLengthBuf (sal_Int32 index)
673 : : {
674 : 0 : sal_Int8* b = NULL;
675 : :
676 : : // Sanity check the parameter number
677 : :
678 : 0 : if ((index >= 1) &&
679 : : (index <= numParams))
680 : : {
681 : 0 : b = boundParams[index - 1].getBindLengthBuffer ();
682 : : }
683 : :
684 : 0 : return b;
685 : : }
686 : : // -------------------------------------------------------------------------
687 : :
688 : : //--------------------------------------------------------------------
689 : : // putParamData
690 : : // Puts parameter data from a previously bound input stream. The
691 : : // input stream was bound using SQL_LEN_DATA_AT_EXEC.
692 : : //--------------------------------------------------------------------
693 : :
694 : 0 : void OPreparedStatement::putParamData (sal_Int32 index) throw(SQLException)
695 : : {
696 : : // Sanity check the parameter index
697 : 0 : if ((index < 1) ||
698 : : (index > numParams))
699 : : {
700 : 0 : return;
701 : : }
702 : :
703 : : // We'll transfer up to MAX_PUT_DATA_LENGTH at a time
704 : 0 : Sequence< sal_Int8 > buf( MAX_PUT_DATA_LENGTH );
705 : :
706 : : // Get the information about the input stream
707 : :
708 : 0 : Reference< XInputStream> inputStream = boundParams[index - 1].getInputStream ();
709 : 0 : if ( !inputStream.is() )
710 : : {
711 : 0 : ::connectivity::SharedResources aResources;
712 : 0 : const ::rtl::OUString sError( aResources.getResourceString(STR_NO_INPUTSTREAM));
713 : 0 : throw SQLException (sError, *this,::rtl::OUString(),0,Any());
714 : : }
715 : :
716 : 0 : sal_Int32 maxBytesLeft = boundParams[index - 1].getInputStreamLen ();
717 : :
718 : : // Loop while more data from the input stream
719 : 0 : sal_Int32 haveRead = 0;
720 : : try
721 : : {
722 : :
723 : 0 : do
724 : : {
725 : 0 : sal_Int32 toReadThisRound = ::std::min( MAX_PUT_DATA_LENGTH, maxBytesLeft );
726 : :
727 : : // Read some data from the input stream
728 : 0 : haveRead = inputStream->readBytes( buf, toReadThisRound );
729 : : OSL_ENSURE( haveRead == buf.getLength(), "OPreparedStatement::putParamData: inconsistency!" );
730 : :
731 : 0 : if ( !haveRead )
732 : : // no more data in the stream - the given stream length was a maximum which could not be
733 : : // fulfilled by the stream
734 : 0 : break;
735 : :
736 : : // Put the data
737 : : OSL_ENSURE( m_aStatementHandle, "OPreparedStatement::putParamData: StatementHandle is null!" );
738 : 0 : N3SQLPutData ( m_aStatementHandle, buf.getArray(), buf.getLength() );
739 : :
740 : : // decrement the number of bytes still needed
741 : 0 : maxBytesLeft -= haveRead;
742 : : }
743 : : while ( maxBytesLeft > 0 );
744 : : }
745 : 0 : catch (const IOException& ex)
746 : : {
747 : :
748 : : // If an I/O exception was generated, turn
749 : : // it into a SQLException
750 : :
751 : 0 : throw SQLException(ex.Message,*this,::rtl::OUString(),0,Any());
752 : 0 : }
753 : : }
754 : : // -------------------------------------------------------------------------
755 : :
756 : : //--------------------------------------------------------------------
757 : : // setStream
758 : : // Sets an input stream as a parameter, using the given SQL type
759 : : //--------------------------------------------------------------------
760 : :
761 : 0 : void OPreparedStatement::setStream(
762 : : sal_Int32 ParameterIndex,
763 : : const Reference< XInputStream>& x,
764 : : SQLLEN length,
765 : : sal_Int32 SQLtype)
766 : : throw(SQLException)
767 : : {
768 : 0 : ::osl::MutexGuard aGuard( m_aMutex );
769 : 0 : checkDisposed(OStatement_BASE::rBHelper.bDisposed);
770 : :
771 : :
772 : 0 : prepareStatement();
773 : :
774 : 0 : checkParameterIndex(ParameterIndex);
775 : : // Get the buffer needed for the length
776 : :
777 : 0 : sal_Int8* lenBuf = getLengthBuf(ParameterIndex);
778 : :
779 : : // Allocate a new buffer for the parameter data. This buffer
780 : : // will be returned by SQLParamData (it is set to the parameter
781 : : // number, a 4-sal_Int8 integer)
782 : :
783 : 0 : sal_Int8* dataBuf = allocBindBuf (ParameterIndex, 4);
784 : :
785 : : // Bind the parameter with SQL_LEN_DATA_AT_EXEC
786 : 0 : SQLSMALLINT Ctype = SQL_C_CHAR;
787 : 0 : SQLLEN atExec = SQL_LEN_DATA_AT_EXEC (length);
788 : 0 : memcpy (dataBuf, &ParameterIndex, sizeof(ParameterIndex));
789 : 0 : memcpy (lenBuf, &atExec, sizeof (atExec));
790 : :
791 : 0 : if ((SQLtype == SQL_BINARY) || (SQLtype == SQL_VARBINARY) || (SQLtype == SQL_LONGVARBINARY))
792 : 0 : Ctype = SQL_C_BINARY;
793 : :
794 : :
795 : : OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
796 : 0 : N3SQLBindParameter(m_aStatementHandle,
797 : : (SQLUSMALLINT)ParameterIndex,
798 : : (SQLUSMALLINT)SQL_PARAM_INPUT,
799 : : Ctype,
800 : : (SQLSMALLINT)SQLtype,
801 : : (SQLULEN)length,
802 : : 0,
803 : : dataBuf,
804 : : sizeof(ParameterIndex),
805 : 0 : (SQLLEN*)lenBuf);
806 : :
807 : : // Save the input stream
808 : 0 : boundParams[ParameterIndex - 1].setInputStream (x, length);
809 : 0 : }
810 : : // -------------------------------------------------------------------------
811 : :
812 : : // -------------------------------------------------------------------------
813 : :
814 : 0 : void OPreparedStatement::FreeParams()
815 : : {
816 : 0 : numParams = 0;
817 : 0 : delete [] boundParams;
818 : 0 : boundParams = NULL;
819 : 0 : }
820 : : // -------------------------------------------------------------------------
821 : 0 : void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception)
822 : : {
823 : : try
824 : : {
825 : 0 : switch(nHandle)
826 : : {
827 : : case PROPERTY_ID_RESULTSETCONCURRENCY:
828 : 0 : if(!isPrepared())
829 : 0 : setResultSetConcurrency(comphelper::getINT32(rValue));
830 : 0 : break;
831 : : case PROPERTY_ID_RESULTSETTYPE:
832 : 0 : if(!isPrepared())
833 : 0 : setResultSetType(comphelper::getINT32(rValue));
834 : 0 : break;
835 : : case PROPERTY_ID_FETCHDIRECTION:
836 : 0 : if(!isPrepared())
837 : 0 : setFetchDirection(comphelper::getINT32(rValue));
838 : 0 : break;
839 : : case PROPERTY_ID_USEBOOKMARKS:
840 : 0 : if(!isPrepared())
841 : 0 : setUsingBookmarks(comphelper::getBOOL(rValue));
842 : 0 : break;
843 : : default:
844 : 0 : OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle,rValue);
845 : : }
846 : : }
847 : 0 : catch(const SQLException&)
848 : : {
849 : : // throw Exception(e.Message,*this);
850 : : }
851 : 0 : }
852 : : // -----------------------------------------------------------------------------
853 : 0 : void OPreparedStatement::prepareStatement()
854 : : {
855 : 0 : if(!isPrepared())
856 : : {
857 : : OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
858 : 0 : ::rtl::OString aSql(::rtl::OUStringToOString(m_sSqlStatement,getOwnConnection()->getTextEncoding()));
859 : 0 : SQLRETURN nReturn = N3SQLPrepare(m_aStatementHandle,(SDB_ODBC_CHAR *) aSql.getStr(),aSql.getLength());
860 : 0 : OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
861 : 0 : m_bPrepared = sal_True;
862 : 0 : initBoundParam();
863 : : }
864 : 0 : }
865 : : // -----------------------------------------------------------------------------
866 : 0 : void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex)
867 : : {
868 : 0 : if( !_parameterIndex || _parameterIndex > numParams)
869 : : {
870 : 0 : ::connectivity::SharedResources aResources;
871 : : const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX,
872 : : "$pos$", ::rtl::OUString::valueOf(_parameterIndex),
873 : : "$count$", ::rtl::OUString::valueOf((sal_Int32)numParams)
874 : 0 : ));
875 : 0 : SQLException aNext(sError,*this, ::rtl::OUString(),0,Any());
876 : :
877 : 0 : ::dbtools::throwInvalidIndexException(*this,makeAny(aNext));
878 : : }
879 : 0 : }
880 : : // -----------------------------------------------------------------------------
881 : 0 : OResultSet* OPreparedStatement::createResulSet()
882 : : {
883 : 0 : OResultSet* pReturn = new OResultSet(m_aStatementHandle,this);
884 : 0 : pReturn->setMetaData(getMetaData());
885 : 0 : return pReturn;
886 : : }
887 : : // -----------------------------------------------------------------------------
888 : :
889 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|