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